2 * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Write vcg representation of firm to file.
23 * @author Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt,
37 #include "irgraph_t.h"
51 #include "callgraph.h"
52 #include "irextbb_t.h"
54 #include "dbginfo_t.h"
68 typedef struct pns_lookup {
69 long nr; /**< the proj number */
70 const char *name; /**< the name of the Proj */
73 typedef struct proj_lookup {
74 unsigned code; /**< the opcode of the Proj predecessor */
75 unsigned num_data; /**< number of data entries */
76 const pns_lookup_t *data; /**< the data */
79 #include "gen_irdump.c.inl"
81 /** Dump only irgs with names that start with this prefix. */
82 static ident *dump_file_filter_id = NULL;
84 static ir_dump_flags_t flags =
85 ir_dump_flag_blocks_as_subgraphs |
86 ir_dump_flag_keepalive_edges |
87 ir_dump_flag_ld_names |
88 ir_dump_flag_back_edges |
89 ir_dump_flag_consts_local |
90 ir_dump_flag_analysed_types |
91 ir_dump_flag_entities_in_hierarchy |
92 ir_dump_flag_number_label;
94 static ird_color_t overrule_nodecolor = ird_color_default_node;
96 /** The vcg node attribute hook. */
97 static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
98 /** The vcg edge attribute hook. */
99 static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
100 /** The vcg dump block edge hook */
101 static dump_node_edge_func dump_block_edge_hook = NULL;
102 /** The vcg dump node edge hook. */
103 static dump_node_edge_func dump_node_edge_hook = NULL;
105 void set_dump_node_edge_hook(dump_node_edge_func func)
107 dump_node_edge_hook = func;
110 dump_node_edge_func get_dump_node_edge_hook(void)
112 return dump_node_edge_hook;
115 void set_dump_block_edge_hook(dump_node_edge_func func)
117 dump_block_edge_hook = func;
120 dump_node_edge_func get_dump_block_edge_hook(void)
122 return dump_node_edge_hook;
125 void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
127 dump_node_vcgattr_hook = hook;
130 void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
132 dump_edge_vcgattr_hook = hook;
135 void ir_set_dump_flags(ir_dump_flags_t new_flags)
140 void ir_add_dump_flags(ir_dump_flags_t new_flags)
145 void ir_remove_dump_flags(ir_dump_flags_t to_remove)
150 ir_dump_flags_t ir_get_dump_flags(void)
155 /** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
156 * are set, else returns dump_const_local_flag.
158 static bool get_opt_dump_const_local(void)
160 return (flags & ir_dump_flag_out_edges)
161 || (flags & ir_dump_flag_loops)
162 || (flags & ir_dump_flag_consts_local)
163 || (flags & ir_dump_flag_iredges);
166 static char *dump_filter;
168 void ir_set_dump_filter(const char *new_filter)
171 dump_filter = xstrdup(new_filter);
174 const char *ir_get_dump_filter(void)
179 int ir_should_dump(const char *name)
183 if (dump_filter == NULL || dump_filter[0] == '\0')
186 for (n = name, f = dump_filter; *f != '\0' && *n != '\0';
194 /* -------------- some extended helper functions ----------------- */
196 const char *get_mode_name_ex(const ir_mode *mode, int *bad)
199 return get_mode_name(mode);
205 #define CUSTOM_COLOR_BASE 100
206 static const char *color_names[ird_color_count];
207 static const char *color_rgb[ird_color_count];
208 static struct obstack color_obst;
210 /** define a custom color. */
211 static void custom_color(int num, const char *rgb_def)
213 assert(num < ird_color_count);
214 obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
215 obstack_1grow(&color_obst, '\0');
217 color_rgb[num] = rgb_def;
218 color_names[num] = (const char*)obstack_finish(&color_obst);
221 /** Define a named color. */
222 static void named_color(int num, const char *name)
224 assert(num < ird_color_count);
225 color_rgb[num] = NULL;
226 color_names[num] = name;
229 /** Initializes the used colors. */
230 static void init_colors(void)
232 static int initialized = 0;
236 obstack_init(&color_obst);
238 custom_color(ird_color_prog_background, "204 204 204");
239 custom_color(ird_color_block_background, "255 255 0");
240 custom_color(ird_color_dead_block_background, "190 150 150");
241 named_color(ird_color_block_inout, "lightblue");
242 named_color(ird_color_default_node, "white");
243 custom_color(ird_color_memory, "153 153 255");
244 custom_color(ird_color_controlflow, "255 153 153");
245 custom_color(ird_color_const, "204 255 255");
246 custom_color(ird_color_proj, "255 255 153");
247 custom_color(ird_color_uses_memory, "153 153 255");
248 custom_color(ird_color_phi, "105 255 105");
249 custom_color(ird_color_anchor, "100 100 255");
250 named_color(ird_color_error, "red");
251 custom_color(ird_color_entity, "204 204 255");
257 * Prints the VCG color to a file.
259 static void print_vcg_color(FILE *out, ird_color_t color)
261 assert(color < ird_color_count);
262 fprintf(out, "color:%s", color_names[color]);
266 * Prints the edge kind of a given IR node.
268 * Projs should be dumped near their predecessor, so they get "nearedge".
270 static void print_node_edge_kind(FILE *out, ir_node *node)
273 fprintf(out, "nearedge: ");
275 fprintf(out, "edge: ");
280 * Prints the edge from a type S to a type T with additional info fmt, ...
283 static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
288 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
289 fprintf(F, " targetname: "); PRINT_TYPEID(T);
290 ir_vfprintf(F, fmt, ap);
296 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
299 static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
304 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
305 fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
306 ir_vfprintf(F, fmt, ap);
312 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
315 static void print_ent_ent_edge(FILE *F, const ir_entity *ent1, const ir_entity *ent2, int backedge, ird_color_t color, const char *fmt, ...)
321 fprintf(F, "backedge: { sourcename: \"");
323 fprintf(F, "edge: { sourcename: \"");
325 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2); fprintf(F, "\"");
326 ir_vfprintf(F, fmt, ap);
328 if (color != ird_color_none)
329 print_vcg_color(F, color);
335 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
338 static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
343 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
344 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
345 ir_vfprintf(F, fmt, ap);
351 * Prints the edge from a node irn to a type tp with additional info fmt, ...
354 static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
359 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
360 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
361 ir_vfprintf(F, fmt, ap);
367 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
370 static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
375 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
376 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
378 ir_vfprintf(F, fmt, ap);
384 * Prints the edge from an entity ent to a node irn with additional info fmt, ...
387 static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
392 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
393 fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
394 ir_vfprintf(F, fmt, ap);
400 * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
403 static void print_enum_item_edge(FILE *F, const ir_type *tp, size_t item, const char *fmt, ...)
408 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
409 fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
410 ir_vfprintf(F, fmt, ap);
415 /*-----------------------------------------------------------------*/
416 /* global and ahead declarations */
417 /*-----------------------------------------------------------------*/
419 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
421 /*-----------------------------------------------------------------*/
422 /* Helper functions. */
423 /*-----------------------------------------------------------------*/
426 * This map is used as a private link attr to be able to call dumper
427 * anywhere without destroying link fields.
429 static pmap *irdump_link_map = NULL;
431 /** NOT A STANDARD LIBFIRM INIT METHOD
433 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
434 * are off, we want to have as few interferences as possible. Therefore the
435 * initialization is performed lazily and not called from within init_firm.
437 * Creates the link attribute map. */
438 static void init_irdump(void)
440 /* We need a new, empty map. */
441 if (irdump_link_map) pmap_destroy(irdump_link_map);
442 irdump_link_map = pmap_create();
443 if (!dump_file_filter_id)
444 dump_file_filter_id = new_id_from_str("");
448 * Returns the private link field.
450 static void *ird_get_irn_link(const ir_node *n)
453 if (irdump_link_map == NULL)
456 if (pmap_contains(irdump_link_map, n))
457 res = pmap_get(irdump_link_map, n);
462 * Sets the private link field.
464 static void ird_set_irn_link(const ir_node *n, void *x)
466 if (irdump_link_map == NULL)
468 pmap_insert(irdump_link_map, n, x);
472 * Gets the private link field of an irg.
474 static void *ird_get_irg_link(const ir_graph *irg)
477 if (irdump_link_map == NULL)
480 if (pmap_contains(irdump_link_map, irg))
481 res = pmap_get(irdump_link_map, irg);
486 * Sets the private link field of an irg.
488 static void ird_set_irg_link(const ir_graph *irg, void *x)
490 if (irdump_link_map == NULL)
492 pmap_insert(irdump_link_map, irg, x);
496 * Walker, clears the private link field.
498 static void clear_link(ir_node *node, void *env)
501 ird_set_irn_link(node, NULL);
505 * If the entity has a ld_name, returns it if the dump_ld_name is set,
506 * else returns the name of the entity.
508 static const char *_get_ent_dump_name(const ir_entity *ent, bool dump_ld_name)
511 return "<NULL entity>";
513 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
514 if (ent->ld_name != NULL)
515 return get_id_str(ent->ld_name);
517 return get_id_str(ent->name);
520 const char *get_ent_dump_name(const ir_entity *ent)
522 return _get_ent_dump_name(ent, flags & ir_dump_flag_ld_names);
525 const char *get_irg_dump_name(const ir_graph *irg)
527 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
528 return _get_ent_dump_name(get_irg_entity(irg), true);
532 * Returns non-zero if a node is in floating state.
534 static int node_floats(const ir_node *n)
536 return ((get_irn_pinned(n) == op_pin_state_floats) &&
537 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
541 * Walker that visits the anchors
543 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
545 if ((flags & ir_dump_flag_all_anchors)
546 || ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
547 irg_walk_anchors(irg, pre, post, env);
549 irg_walk_graph(irg, pre, post, env);
554 * Walker, allocates an array for all blocks and puts their non-floating
555 * nodes into this array.
557 static void collect_node(ir_node *node, void *env)
562 || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
563 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
564 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
565 ARR_APP1(ir_node *, arr, node);
566 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
568 ir_node * block = get_nodes_block(node);
571 /* this node is in a Bad block, so we must place it into the graph's list */
572 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
573 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
574 ARR_APP1(ir_node *, arr, node);
575 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
577 ird_set_irn_link(node, ird_get_irn_link(block));
578 ird_set_irn_link(block, node);
583 /** Construct lists to walk ir block-wise.
585 * Collects all blocks, nodes not op_pin_state_pinned,
586 * Bad, NoMem and Unknown into a flexible array in link field of
587 * irg they belong to. Sets the irg link field to NULL in all
588 * graphs not visited.
589 * Free the list with DEL_ARR_F().
591 static ir_node **construct_block_lists(ir_graph *irg)
594 int walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
595 ir_graph *rem = current_ir_graph;
597 current_ir_graph = irg;
600 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
603 for (i = get_irp_n_irgs(); i > 0;)
604 ird_set_irg_link(get_irp_irg(--i), NULL);
606 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
609 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
612 current_ir_graph = rem;
613 return (ir_node**)ird_get_irg_link(irg);
616 typedef struct list_tuple {
618 ir_extblk **extbb_list;
621 /** Construct lists to walk IR extended block-wise.
622 * Free the lists in the tuple with DEL_ARR_F(). Sets the irg link field to
623 * NULL in all graphs not visited.
625 static list_tuple *construct_extblock_lists(ir_graph *irg)
627 ir_node **blk_list = construct_block_lists(irg);
629 ir_graph *rem = current_ir_graph;
630 list_tuple *lists = XMALLOC(list_tuple);
632 current_ir_graph = irg;
634 lists->blk_list = NEW_ARR_F(ir_node *, 0);
635 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
637 inc_irg_block_visited(irg);
638 for (i = 0, n = ARR_LEN(blk_list); i < n; ++i) {
641 if (is_Block(blk_list[i])) {
642 ext = get_Block_extbb(blk_list[i]);
644 if (extbb_not_visited(ext)) {
645 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
646 mark_extbb_visited(ext);
649 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
653 current_ir_graph = rem;
654 ird_set_irg_link(irg, lists);
658 void dump_node_opcode(FILE *F, ir_node *n)
660 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
662 /* call the dump_node operation if available */
663 if (ops->dump_node) {
664 ops->dump_node(F, n, dump_node_opcode_txt);
668 /* implementation for default nodes */
669 switch (get_irn_opcode(n)) {
671 switch (get_SymConst_kind(n)) {
672 case symconst_addr_ent:
673 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
675 case symconst_ofs_ent:
676 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
678 case symconst_type_size:
679 ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
681 case symconst_type_align:
682 ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
684 case symconst_enum_const:
685 fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
691 if (get_Load_unaligned(n) == align_non_aligned)
693 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), NULL));
696 if (get_Store_unaligned(n) == align_non_aligned)
698 fprintf(F, "%s", get_irn_opname(n));
701 if (n == get_irg_start_block(get_irn_irg(n)))
703 if (n == get_irg_end_block(get_irn_irg(n)))
705 fprintf(F, "%s%s", get_irn_opname(n),
706 (flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
709 if (get_Conv_strict(n))
710 fprintf(F, "strict");
711 fprintf(F, "%s", get_irn_opname(n));
714 fprintf(F, "%s", get_irn_opname(n));
715 if (get_Div_no_remainder(n))
717 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), NULL));
720 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), NULL));
723 fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
727 fprintf(F, "%s", get_irn_opname(n));
732 * Dump the mode of a node n to a file F.
733 * Ignore modes that are "always known".
735 static void dump_node_mode(FILE *F, ir_node *n)
737 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
741 /* call the dump_node operation if available */
742 if (ops->dump_node) {
743 ops->dump_node(F, n, dump_node_mode_txt);
747 /* default implementation */
748 iro = get_irn_opcode(n);
760 mode = get_irn_mode(n);
762 if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
763 (mode != mode_T || iro == iro_Proj))
764 fprintf(F, "%s", get_mode_name_ex(mode, NULL));
769 * Dump the type of a node n to a file F if it's known.
771 static int dump_node_typeinfo(FILE *F, ir_node *n)
775 if (ir_get_dump_flags() & ir_dump_flag_analysed_types) {
776 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
777 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
778 ir_type *tp = get_irn_typeinfo_type(n);
779 if (tp != firm_none_type) {
780 ir_fprintf(F, "[%+F]", tp);
790 * Dump additional node attributes of some nodes to a file F.
792 static void dump_node_nodeattr(FILE *F, ir_node *n)
797 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
799 /* call the dump_node operation if available */
800 if (ops->dump_node) {
801 ops->dump_node(F, n, dump_node_nodeattr_txt);
805 switch (get_irn_opcode(n)) {
807 ir_fprintf(F, "%T ", get_Const_tarval(n));
811 pred = get_Proj_pred(n);
812 proj_nr = get_Proj_proj(n);
813 code = get_irn_opcode(pred);
815 if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
816 fprintf(F, "Arg %ld ", proj_nr);
817 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
818 fprintf(F, "%ld ", proj_nr);
820 unsigned i, j, f = 0;
822 for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
823 if (code == proj_lut[i].code) {
824 for (j = 0; j < proj_lut[i].num_data; ++j) {
825 if (proj_nr == proj_lut[i].data[j].nr) {
826 fprintf(F, "%s ", proj_lut[i].data[j].name);
835 fprintf(F, "%ld ", proj_nr);
836 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
837 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
839 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
845 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
848 ir_fprintf(F, "(%+F)", get_Cast_type(n));
851 fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
854 fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
857 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
865 static void dump_node_ana_vals(FILE *F, ir_node *n)
872 void dump_node_label(FILE *F, ir_node *n)
874 dump_node_opcode(F, n);
876 dump_node_mode(F, n);
878 dump_node_typeinfo(F, n);
879 dump_node_nodeattr(F, n);
880 if (flags & ir_dump_flag_number_label) {
881 fprintf(F, "%ld", get_irn_node_nr(n));
883 if (flags & ir_dump_flag_idx_label) {
884 fprintf(F, ":%u", get_irn_idx(n));
889 * Dumps the attributes of a node n into the file F.
890 * Currently this is only the color of a node.
892 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
898 print_vcg_color(F, ird_color_error);
902 if (dump_node_vcgattr_hook != NULL) {
903 dump_node_vcgattr_hook(F, node, local);
907 n = local ? local : node;
909 if (overrule_nodecolor != ird_color_default_node) {
910 print_vcg_color(F, overrule_nodecolor);
914 mode = get_irn_mode(n);
915 if (mode == mode_M) {
916 print_vcg_color(F, ird_color_memory);
919 if (mode == mode_X) {
920 print_vcg_color(F, ird_color_controlflow);
924 switch (get_irn_opcode(n)) {
927 print_vcg_color(F, ird_color_anchor);
930 print_vcg_color(F, ird_color_error);
933 print_vcg_color(F, ird_color_block_background);
936 print_vcg_color(F, ird_color_phi);
939 print_vcg_color(F, ird_color_memory);
943 print_vcg_color(F, ird_color_const);
946 print_vcg_color(F, ird_color_proj);
949 ir_op *op = get_irn_op(node);
951 if (is_op_constlike(op)) {
952 print_vcg_color(F, ird_color_const);
953 } else if (is_op_uses_memory(op)) {
954 print_vcg_color(F, ird_color_uses_memory);
955 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
956 print_vcg_color(F, ird_color_controlflow);
962 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
964 hook_entry_t *info = XMALLOCZ(hook_entry_t);
966 info->hook._hook_node_info = cb;
967 info->context = data;
968 register_hook(hook_node_info, info);
973 void dump_remove_node_info_callback(void *handle)
975 hook_entry_t *info = (hook_entry_t*)handle;
976 unregister_hook(hook_node_info, info);
981 * Dump the node information of a node n to a file F.
983 static void dump_node_info(FILE *F, ir_node *n)
985 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
987 fprintf(F, " info1: \"");
988 dump_irnode_to_file(F, n);
989 /* call the dump_node operation if available */
991 ops->dump_node(F, n, dump_node_info_txt);
993 /* allow additional info to be added */
994 hook_node_info(F, n);
998 static int is_constlike_node(const ir_node *node)
1000 const ir_op *op = get_irn_op(node);
1001 return is_op_constlike(op);
1005 /** outputs the predecessors of n, that are constants, local. I.e.,
1006 generates a copy of the constant predecessors for each node called with. */
1007 static void dump_const_node_local(FILE *F, ir_node *n)
1010 if (!get_opt_dump_const_local()) return;
1012 /* Use visited flag to avoid outputting nodes twice.
1013 initialize it first. */
1014 for (i = 0; i < get_irn_arity(n); i++) {
1015 ir_node *con = get_irn_n(n, i);
1016 if (is_constlike_node(con)) {
1017 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1021 for (i = 0; i < get_irn_arity(n); i++) {
1022 ir_node *con = get_irn_n(n, i);
1023 if (is_constlike_node(con) && !irn_visited_else_mark(con)) {
1024 /* Generate a new name for the node by appending the names of
1026 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1027 fprintf(F, " label: \"");
1028 dump_node_label(F, con);
1030 dump_node_info(F, con);
1031 dump_node_vcgattr(F, n, con, 0);
1037 /** If the block of an edge is a const_like node, dump it local with an edge */
1038 static void dump_const_block_local(FILE *F, ir_node *n)
1042 if (!get_opt_dump_const_local()) return;
1044 blk = get_nodes_block(n);
1045 if (is_constlike_node(blk)) {
1046 /* Generate a new name for the node by appending the names of
1048 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1049 fprintf(F, "\" label: \"");
1050 dump_node_label(F, blk);
1052 dump_node_info(F, blk);
1053 dump_node_vcgattr(F, n, blk, 0);
1056 fprintf(F, "edge: { sourcename: \"");
1058 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1060 if (dump_edge_vcgattr_hook) {
1062 if (dump_edge_vcgattr_hook(F, n, -1)) {
1066 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1071 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1076 * prints the error message of a node to a file F as info2.
1078 static void print_node_error(FILE *F, const char *err_msg)
1083 fprintf(F, " info2: \"%s\"", err_msg);
1087 * prints debug messages of a node to file F as info3.
1089 static void print_dbg_info(FILE *F, dbg_info *dbg)
1093 ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1095 fprintf(F, " info3: \"%s\"\n", buf);
1099 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1109 static void dump_node(FILE *F, ir_node *n)
1114 if (get_opt_dump_const_local() && is_constlike_node(n))
1117 /* dump this node */
1118 fputs("node: {title: \"", F);
1122 fputs(" label: \"", F);
1123 bad = ! irn_verify_irg_dump(n, current_ir_graph, &p);
1124 dump_node_label(F, n);
1125 dump_node_ana_vals(F, n);
1126 //dump_node_ana_info(F, n);
1129 if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1130 //fputs(" node_class:23", F);
1133 dump_node_info(F, n);
1134 print_node_error(F, p);
1135 print_dbg_info(F, get_irn_dbg_info(n));
1136 dump_node_vcgattr(F, n, NULL, bad);
1138 dump_const_node_local(F, n);
1140 if (dump_node_edge_hook)
1141 dump_node_edge_hook(F, n);
1144 /** dump the edge to the block this node belongs to */
1145 static void dump_ir_block_edge(FILE *F, ir_node *n)
1147 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1149 ir_node *block = get_nodes_block(n);
1151 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1152 dump_const_block_local(F, n);
1154 fprintf(F, "edge: { sourcename: \"");
1156 fprintf(F, "\" targetname: ");
1157 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1159 if (dump_edge_vcgattr_hook) {
1161 if (dump_edge_vcgattr_hook(F, n, -1)) {
1165 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1170 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1175 static void print_data_edge_vcgattr(FILE *F, ir_node *from, int to)
1178 * do not use get_nodes_block() here, will fail
1179 * if the irg is not pinned.
1181 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1182 fprintf(F, INTRA_DATA_EDGE_ATTR);
1184 fprintf(F, INTER_DATA_EDGE_ATTR);
1187 static void print_mem_edge_vcgattr(FILE *F, ir_node *from, int to)
1190 * do not use get_nodes_block() here, will fail
1191 * if the irg is not pinned.
1193 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1194 fprintf(F, INTRA_MEM_EDGE_ATTR);
1196 fprintf(F, INTER_MEM_EDGE_ATTR);
1199 /** Print the vcg attributes for the edge from node "from" to its "to"th input */
1200 static void print_edge_vcgattr(FILE *F, ir_node *from, int to)
1204 if (dump_edge_vcgattr_hook)
1205 if (dump_edge_vcgattr_hook(F, from, to))
1208 if ((flags & ir_dump_flag_back_edges) && is_backedge(from, to))
1209 fprintf(F, BACK_EDGE_ATTR);
1211 switch (get_irn_opcode(from)) {
1213 fprintf(F, CF_EDGE_ATTR);
1215 case iro_Start: break;
1218 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1219 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1221 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1225 if (is_Proj(from)) {
1226 if (get_irn_mode(from) == mode_M)
1227 print_mem_edge_vcgattr(F, from, to);
1228 else if (get_irn_mode(from) == mode_X)
1229 fprintf(F, CF_EDGE_ATTR);
1231 print_data_edge_vcgattr(F, from, to);
1233 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1234 print_mem_edge_vcgattr(F, from, to);
1235 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1236 fprintf(F, CF_EDGE_ATTR);
1238 print_data_edge_vcgattr(F, from, to);
1242 /** dump edges to our inputs */
1243 static void dump_ir_data_edges(FILE *F, ir_node *n)
1247 if (!(flags & ir_dump_flag_keepalive_edges) && is_End(n)) {
1248 /* the End node has only keep-alive edges */
1252 /* dump the dependency edges. */
1253 num = get_irn_deps(n);
1254 for (i = 0; i < num; ++i) {
1255 ir_node *dep = get_irn_dep(n, i);
1258 print_node_edge_kind(F, n);
1259 fprintf(F, "{sourcename: \"");
1261 fprintf(F, "\" targetname: ");
1262 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1263 PRINT_CONSTID(n, dep);
1269 fprintf(F, " label: \"%d\" ", i);
1270 fprintf(F, " color: darkgreen}\n");
1274 num = get_irn_arity(n);
1275 for (i = 0; i < num; i++) {
1276 ir_node *pred = get_irn_n(n, i);
1279 if ((flags & ir_dump_flag_back_edges) && is_backedge(n, i)) {
1280 fprintf(F, "backedge: {sourcename: \"");
1282 print_node_edge_kind(F, n);
1283 fprintf(F, "{sourcename: \"");
1286 fprintf(F, "\" targetname: ");
1287 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1288 PRINT_CONSTID(n, pred);
1290 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1292 fprintf(F, " label: \"%d\" ", i);
1293 print_edge_vcgattr(F, n, i);
1301 static void dump_ir_edges(ir_node *node, void *env)
1304 FILE *F = (FILE*)env;
1305 const ir_edge_t *edge;
1307 foreach_out_edge(node, edge) {
1308 ir_node *succ = get_edge_src_irn(edge);
1310 print_node_edge_kind(F, succ);
1311 fprintf(F, "{sourcename: \"");
1313 fprintf(F, "\" targetname: \"");
1317 fprintf(F, " label: \"%d\" ", i);
1318 fprintf(F, OUT_EDGE_ATTR);
1325 /** Dumps a node and its edges but not the block edge */
1326 static void dump_node_wo_blockedge(ir_node *n, void *env)
1328 FILE *F = (FILE*)env;
1330 dump_ir_data_edges(F, n);
1333 /** Dumps a node and its edges. */
1334 static void dump_node_with_edges(ir_node *n, void *env)
1336 FILE *F = (FILE*)env;
1337 dump_node_wo_blockedge(n, env);
1338 if (!node_floats(n))
1339 dump_ir_block_edge(F, n);
1342 /** Dumps a const-like node. */
1343 static void dump_const_node(ir_node *n, void *env)
1345 if (is_Block(n)) return;
1346 dump_node_wo_blockedge(n, env);
1349 /***********************************************************************/
1350 /* the following routines dump the nodes/irgs bracketed to graphs. */
1351 /***********************************************************************/
1353 /** Dumps a constant expression as entity initializer, array bound ... */
1354 static void dump_const_expression(FILE *F, ir_node *value)
1356 ir_graph *rem = current_ir_graph;
1357 ir_dump_flags_t old_flags = ir_get_dump_flags();
1358 ir_remove_dump_flags(ir_dump_flag_consts_local);
1360 current_ir_graph = get_const_code_irg();
1361 irg_walk(value, dump_const_node, NULL, F);
1362 /* Decrease visited flag so that we walk with the same flag for the next
1363 expression. This guarantees that we don't dump the same node twice,
1364 as for const expressions cse is performed to save memory. */
1365 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1367 ir_set_dump_flags(old_flags);
1368 current_ir_graph = rem;
1371 /** Dump a block as graph containing its nodes.
1373 * Expects to find nodes belonging to the block as list in its
1375 * Dumps the edges of all nodes including itself. */
1376 static void dump_whole_block(FILE *F, ir_node *block)
1379 ird_color_t color = ird_color_block_background;
1381 assert(is_Block(block));
1383 fprintf(F, "graph: { title: \"");
1384 PRINT_NODEID(block);
1385 fprintf(F, "\" label: \"");
1386 dump_node_label(F, block);
1388 /* colorize blocks */
1389 if (! get_Block_matured(block))
1390 color = ird_color_block_background;
1392 fprintf(F, "\" status:clustered ");
1393 print_vcg_color(F, color);
1396 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1397 dump_node_info(F, block);
1398 print_dbg_info(F, get_irn_dbg_info(block));
1400 /* dump the blocks edges */
1401 dump_ir_data_edges(F, block);
1403 if (dump_block_edge_hook)
1404 dump_block_edge_hook(F, block);
1406 /* dump the nodes that go into the block */
1407 for (node = (ir_node*)ird_get_irn_link(block); node; node = (ir_node*)ird_get_irn_link(node)) {
1409 dump_ir_data_edges(F, node);
1412 /* Close the vcg information for the block */
1414 dump_const_node_local(F, block);
1418 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1419 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1420 static void dump_block_graph(FILE *F, ir_graph *irg)
1423 ir_graph *rem = current_ir_graph;
1424 ir_node **arr = (ir_node**)ird_get_irg_link(irg);
1425 current_ir_graph = irg;
1427 for (i = 0, n = ARR_LEN(arr); i < n; ++i) {
1428 ir_node *node = arr[i];
1429 if (is_Block(node)) {
1430 /* Dumps the block and all the nodes in the block, which are to
1431 be found in Block->link. */
1432 dump_whole_block(F, node);
1434 /* Nodes that are not in a Block. */
1436 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1437 dump_const_block_local(F, node);
1439 dump_ir_data_edges(F, node);
1441 if ((flags & ir_dump_flag_iredges) && edges_activated(irg))
1442 dump_ir_edges(node, F);
1445 if ((flags & ir_dump_flag_loops)
1446 && is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1447 dump_loop_nodes_into_graph(F, irg);
1449 current_ir_graph = rem;
1453 * Dump the info for an irg.
1454 * Parsed by XVCG but not shown. use yComp.
1456 static void dump_graph_info(FILE *F, ir_graph *irg)
1458 fprintf(F, "info1: \"");
1459 dump_entity_to_file(F, get_irg_entity(irg));
1462 /* dump graph state */
1463 fprintf(F, "state:");
1464 if (is_irg_state(irg, IR_GRAPH_STATE_ARCH_DEP))
1465 fprintf(F, " arch_dep");
1466 if (is_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED))
1467 fprintf(F, " modeb_lowered");
1468 if (is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
1469 fprintf(F, " normalisation2");
1470 if (is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING))
1471 fprintf(F, " implicit_bitfield_masking");
1472 if (is_irg_state(irg, IR_GRAPH_STATE_OPTIMIZE_UNREACHABLE_CODE))
1473 fprintf(F, " optimize_unreachable_code");
1474 if (is_irg_state(irg, IR_GRAPH_STATE_NO_CRITICAL_EDGES))
1475 fprintf(F, " no_critical_edges");
1476 if (is_irg_state(irg, IR_GRAPH_STATE_NO_BADS))
1477 fprintf(F, " no_bads");
1478 if (is_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE))
1479 fprintf(F, " no_unreachable_code");
1480 if (is_irg_state(irg, IR_GRAPH_STATE_ONE_RETURN))
1481 fprintf(F, " one_return");
1482 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE))
1483 fprintf(F, " consistent_dominance");
1484 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE))
1485 fprintf(F, " consistent_postdominance");
1486 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUT_EDGES))
1487 fprintf(F, " consistent_out_edges");
1488 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))
1489 fprintf(F, " consistent_outs");
1490 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1491 fprintf(F, " consistent_loopinfo");
1492 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE))
1493 fprintf(F, " consistent_entity_usage");
1494 if (is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
1495 fprintf(F, " valid_exended_blocks");
1499 /** Dumps an irg as a graph clustered by block nodes.
1500 * If interprocedural view edges can point to nodes out of this graph.
1502 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1504 ir_entity *ent = get_irg_entity(irg);
1506 fprintf(F, "graph: { title: \"");
1508 fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1509 get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1511 dump_graph_info(F, irg);
1512 print_dbg_info(F, get_entity_dbg_info(ent));
1514 dump_block_graph(F, irg);
1516 /* Close the vcg information for the irg */
1517 fprintf(F, "}\n\n");
1520 /*******************************************************************/
1521 /* Basic type and entity nodes and edges. */
1522 /*******************************************************************/
1524 /** dumps the edges between nodes and their type or entity attributes. */
1525 static void dump_node2type_edges(ir_node *n, void *env)
1527 FILE *F = (FILE*)env;
1530 switch (get_irn_opcode(n)) {
1532 /* @@@ some consts have an entity */
1535 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1536 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1539 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1542 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1545 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1548 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1551 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1559 static int print_type_info(FILE *F, ir_type *tp)
1563 if (get_type_state(tp) == layout_undefined) {
1564 fprintf(F, "state: layout_undefined\n");
1566 fprintf(F, "state: layout_fixed,\n");
1568 if (get_type_mode(tp))
1569 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1570 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1575 static void print_typespecific_info(FILE *F, ir_type *tp)
1577 switch (get_type_tpop_code(tp)) {
1579 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1584 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1585 fprintf(F, "params: %d\n", get_method_n_params(tp));
1586 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1592 case tpo_enumeration:
1604 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
1606 switch (get_type_tpop_code(tp)) {
1608 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1611 fprintf(F, " " TYPE_METH_NODE_ATTR);
1619 case tpo_enumeration:
1630 void dump_type_node(FILE *F, ir_type *tp)
1632 fprintf(F, "node: {title: ");
1634 fprintf(F, " label: \"");
1635 if (tp->dbi != NULL) {
1637 ir_print_type(buf, sizeof(buf), tp);
1638 fprintf(F, "%s '%s'", get_type_tpop_name(tp), buf);
1640 ir_fprintf(F, "%+F", tp);
1642 fputs("\" info1: \"", F);
1643 dump_type_to_file(F, tp);
1645 print_type_dbg_info(F, get_type_dbg_info(tp));
1646 print_typespecific_vcgattr(F, tp);
1650 static void dump_entity_node(FILE *F, ir_entity *ent)
1652 fprintf(F, "node: {title: \"");
1653 PRINT_ENTID(ent); fprintf(F, "\"");
1654 fprintf(F, " label: ");
1655 fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
1657 print_vcg_color(F, ird_color_entity);
1658 fprintf(F, "\n info1: \"");
1660 dump_entity_to_file(F, ent);
1663 print_dbg_info(F, get_entity_dbg_info(ent));
1667 static void dump_enum_item(FILE *F, ir_type *tp, size_t pos)
1670 ir_enum_const *ec = get_enumeration_const(tp, pos);
1671 ident *id = get_enumeration_const_nameid(ec);
1672 ir_tarval *tv = get_enumeration_value(ec);
1675 tarval_snprintf(buf, sizeof(buf), tv);
1677 strncpy(buf, "<not set>", sizeof(buf));
1678 fprintf(F, "node: {title: \"");
1679 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1680 fprintf(F, " label: ");
1681 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1682 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1686 * Dumps a new style initializer.
1688 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
1696 * type-walker: Dumps a type or entity and its edges.
1698 static void dump_type_info(type_or_ent tore, void *env)
1700 FILE *F = (FILE*)env;
1701 size_t i = 0; /* to shutup gcc */
1703 /* dump this type or entity */
1705 switch (get_kind(tore.ent)) {
1707 ir_entity *ent = tore.ent;
1710 dump_entity_node(F, ent);
1712 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1713 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1714 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1715 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1716 if (is_Class_type(get_entity_owner(ent))) {
1717 for (i = get_entity_n_overwrites(ent); i > 0;)
1718 print_ent_ent_edge(F, ent, get_entity_overwrites(ent, --i), 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1720 /* attached subgraphs */
1721 if (! (flags & ir_dump_flag_no_entity_values)) {
1722 if (ent->initializer != NULL) {
1723 /* new style initializers */
1724 dump_entity_initializer(F, ent);
1725 } else if (entity_has_compound_ent_values(ent)) {
1726 /* old style compound entity values */
1727 for (i = get_compound_ent_n_values(ent); i > 0;) {
1728 value = get_compound_ent_value(ent, --i);
1730 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1731 dump_const_expression(F, value);
1732 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ird_color_none, ENT_CORR_EDGE_ATTR, i);
1734 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1735 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1736 get_compound_ent_value_member(ent, i), i);
1745 ir_type *tp = tore.typ;
1746 dump_type_node(F, tp);
1747 /* and now the edges */
1748 switch (get_type_tpop_code(tp)) {
1750 for (i = get_class_n_supertypes(tp); i > 0;) {
1752 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
1754 for (i = get_class_n_members(tp); i > 0;) {
1756 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1760 for (i = get_struct_n_members(tp); i > 0;) {
1762 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1766 for (i = get_method_n_params(tp); i > 0;) {
1768 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
1770 for (i = get_method_n_ress(tp); i > 0;) {
1772 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
1776 for (i = get_union_n_members(tp); i > 0;) {
1778 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
1782 print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
1783 print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
1784 for (i = get_array_n_dimensions(tp); i > 0;) {
1785 ir_node *upper, *lower;
1788 upper = get_array_upper_bound(tp, i);
1789 lower = get_array_lower_bound(tp, i);
1790 print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
1791 print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
1792 dump_const_expression(F, upper);
1793 dump_const_expression(F, lower);
1796 case tpo_enumeration:
1797 for (i = get_enumeration_n_enums(tp); i > 0;) {
1799 dump_enum_item(F, tp, i);
1800 print_enum_item_edge(F, tp, i, "label: \"item %zu\"", i);
1804 print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1811 break; /* case k_type */
1814 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1818 /** For dumping class hierarchies.
1819 * Dumps a class type node and a superclass edge.
1821 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
1823 FILE *F = (FILE*)ctx;
1824 size_t i = 0; /* to shutup gcc */
1826 /* dump this type or entity */
1827 switch (get_kind(tore.ent)) {
1829 ir_entity *ent = tore.ent;
1830 if (get_entity_owner(ent) == get_glob_type()) break;
1831 if (!is_Method_type(get_entity_type(ent)))
1833 if (flags & ir_dump_flag_entities_in_hierarchy
1834 && is_Class_type(get_entity_owner(ent))) {
1836 dump_entity_node(F, ent);
1838 print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
1839 for (i = get_entity_n_overwrites(ent); i > 0;) {
1841 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1847 ir_type *tp = tore.typ;
1848 if (tp == get_glob_type())
1850 switch (get_type_tpop_code(tp)) {
1852 dump_type_node(F, tp);
1853 /* and now the edges */
1854 for (i = get_class_n_supertypes(tp); i > 0;) {
1856 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1861 break; /* case k_type */
1864 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1868 /*******************************************************************/
1869 /* dump analysis information that is expressed in graph terms. */
1870 /*******************************************************************/
1872 /* dump out edges */
1873 static void dump_out_edge(ir_node *n, void *env)
1875 FILE *F = (FILE*)env;
1877 for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
1878 ir_node *succ = get_irn_out(n, i);
1880 print_node_edge_kind(F, succ);
1881 fprintf(F, "{sourcename: \"");
1883 fprintf(F, "\" targetname: \"");
1885 fprintf(F, "\" color: red linestyle: dashed");
1890 static void dump_loop_label(FILE *F, const ir_loop *loop)
1892 fprintf(F, "loop %u", get_loop_depth(loop));
1895 static void dump_loop_info(FILE *F, const ir_loop *loop)
1897 fprintf(F, " info1: \"");
1898 fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
1899 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
1900 fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
1905 static void dump_loop_node(FILE *F, const ir_loop *loop)
1907 fprintf(F, "node: {title: \"");
1909 fprintf(F, "\" label: \"");
1910 dump_loop_label(F, loop);
1912 dump_loop_info(F, loop);
1916 static void dump_loop_node_edge(FILE *F, const ir_loop *loop, size_t i)
1919 fprintf(F, "edge: {sourcename: \"");
1921 fprintf(F, "\" targetname: \"");
1922 PRINT_NODEID(get_loop_element(loop, i).node);
1923 fprintf(F, "\" color: green");
1927 static void dump_loop_son_edge(FILE *F, const ir_loop *loop, size_t i)
1930 fprintf(F, "edge: {sourcename: \"");
1932 fprintf(F, "\" targetname: \"");
1933 PRINT_LOOPID(get_loop_element(loop, i).son);
1934 ir_fprintf(F, "\" color: darkgreen label: \"%zu\"}\n", i);
1937 static void dump_loops(FILE *F, const ir_loop *loop)
1940 size_t n_elements = get_loop_n_elements(loop);
1941 /* dump this loop node */
1942 dump_loop_node(F, loop);
1944 /* dump edges to nodes in loop -- only if it is a real loop */
1945 if (get_loop_depth(loop) != 0) {
1946 for (i = n_elements; i > 0;) {
1947 loop_element element;
1949 element = get_loop_element(loop, i);
1950 if (*element.kind != k_ir_node)
1952 dump_loop_node_edge(F, loop, i);
1955 for (i = n_elements; i > 0;) {
1956 loop_element element;
1958 element = get_loop_element(loop, i);
1959 if (*element.kind != k_ir_loop)
1961 dump_loops(F, element.son);
1962 dump_loop_son_edge(F, loop, i);
1966 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
1968 ir_loop *loop = get_irg_loop(irg);
1971 ir_graph *rem = current_ir_graph;
1972 current_ir_graph = irg;
1974 dump_loops(F, loop);
1976 current_ir_graph = rem;
1982 * dumps the VCG header
1984 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
1988 = (flags & ir_dump_flag_disable_edge_labels) ? "no" : "yes";
1992 if (! layout) layout = "Compilergraph";
1993 if (!orientation) orientation = "bottom_to_top";
1997 "graph: { title: \"ir graph of %s\"\n"
1998 "display_edge_labels: %s\n"
1999 "layoutalgorithm: mindepth //$ \"%s\"\n"
2000 "manhattan_edges: yes\n"
2001 "port_sharing: no\n"
2003 "classname 1: \"intrablock Data\"\n"
2004 "classname 2: \"Block\"\n"
2005 "classname 3: \"Entity type\"\n"
2006 "classname 4: \"Entity owner\"\n"
2007 "classname 5: \"Method Param\"\n"
2008 "classname 6: \"Method Res\"\n"
2009 "classname 7: \"Super\"\n"
2010 "classname 8: \"Union\"\n"
2011 "classname 9: \"Points-to\"\n"
2012 "classname 10: \"Array Element Type\"\n"
2013 "classname 11: \"Overwrites\"\n"
2014 "classname 12: \"Member\"\n"
2015 "classname 13: \"Control Flow\"\n"
2016 "classname 14: \"intrablock Memory\"\n"
2017 "classname 15: \"Dominators\"\n"
2018 "classname 16: \"interblock Data\"\n"
2019 "classname 17: \"interblock Memory\"\n"
2020 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2021 "classname 19: \"Postdominators\"\n"
2022 "classname 20: \"Keep Alive\"\n"
2023 "classname 21: \"Out Edges\"\n"
2024 "classname 22: \"Macro Block Edges\"\n"
2025 //"classname 23: \"NoInput Nodes\"\n"
2026 "infoname 1: \"Attribute\"\n"
2027 "infoname 2: \"Verification errors\"\n"
2028 "infoname 3: \"Debug info\"\n",
2029 name, label, layout, orientation);
2031 for (i = 0; i < ird_color_count; ++i) {
2032 if (color_rgb[i] != NULL) {
2033 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2040 * Dumps the vcg file footer
2042 void dump_vcg_footer(FILE *F)
2049 static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
2053 construct_block_lists(irg);
2056 * If we are in the interprocedural view, we dump not
2057 * only the requested irg but also all irgs that can be reached
2060 for (i = get_irp_n_irgs(); i > 0;) {
2061 ir_graph *other_irg = get_irp_irg(--i);
2062 ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
2066 dump_graph_from_list(out, other_irg);
2071 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
2072 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
2073 static void dump_extblock_graph(FILE *F, ir_graph *irg)
2076 ir_graph *rem = current_ir_graph;
2077 ir_extblk **arr = (ir_extblk**)ird_get_irg_link(irg);
2078 current_ir_graph = irg;
2080 for (i = 0, arr_len = ARR_LEN(arr); i < arr_len; ++i) {
2081 ir_extblk *extbb = arr[i];
2082 ir_node *leader = get_extbb_leader(extbb);
2085 fprintf(F, "graph: { title: \"");
2086 PRINT_EXTBBID(leader);
2087 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
2088 get_irn_node_nr(leader));
2090 for (j = 0, n_blks = ARR_LEN(extbb->blks); j < n_blks; ++j) {
2091 ir_node *node = extbb->blks[j];
2092 if (is_Block(node)) {
2093 /* Dumps the block and all the nodes in the block, which are to
2094 be found in Block->link. */
2095 dump_whole_block(F, node);
2097 /* Nodes that are not in a Block. */
2099 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
2100 dump_const_block_local(F, node);
2102 dump_ir_data_edges(F, node);
2108 if ((flags & ir_dump_flag_loops)
2109 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO)))
2110 dump_loop_nodes_into_graph(F, irg);
2112 current_ir_graph = rem;
2116 static void dump_blocks_extbb_grouped(FILE *F, ir_graph *irg)
2119 ir_entity *ent = get_irg_entity(irg);
2121 if (!is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
2124 construct_extblock_lists(irg);
2126 fprintf(F, "graph: { title: \"");
2128 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2129 get_ent_dump_name(ent));
2131 dump_graph_info(F, irg);
2132 print_dbg_info(F, get_entity_dbg_info(ent));
2134 for (i = get_irp_n_irgs(); i > 0;) {
2135 ir_graph *other_irg = get_irp_irg(--i);
2136 list_tuple *lists = (list_tuple*)ird_get_irg_link(other_irg);
2139 /* dump the extended blocks first */
2140 if (ARR_LEN(lists->extbb_list)) {
2141 ird_set_irg_link(other_irg, lists->extbb_list);
2142 dump_extblock_graph(F, other_irg);
2145 /* we may have blocks without extended blocks, bad for instance */
2146 if (ARR_LEN(lists->blk_list)) {
2147 ird_set_irg_link(other_irg, lists->blk_list);
2148 dump_block_graph(F, other_irg);
2151 DEL_ARR_F(lists->extbb_list);
2152 DEL_ARR_F(lists->blk_list);
2157 /* Close the vcg information for the irg */
2158 fprintf(F, "}\n\n");
2163 void dump_ir_graph_file(FILE *out, ir_graph *irg)
2165 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2168 if (flags & ir_dump_flag_blocks_as_subgraphs) {
2169 if (flags & ir_dump_flag_group_extbb) {
2170 dump_blocks_extbb_grouped(out, irg);
2172 dump_blocks_as_subgraphs(out, irg);
2175 /* dump_node_with_edges must be called in post visiting predecessors */
2176 ird_walk_graph(irg, NULL, dump_node_with_edges, out);
2179 /* dump type info */
2180 if (flags & ir_dump_flag_with_typegraph) {
2181 ir_graph *rem = current_ir_graph;
2182 current_ir_graph = irg;
2184 type_walk_irg(irg, dump_type_info, NULL, out);
2185 inc_irg_visited(get_const_code_irg());
2186 /* dump edges from graph to type info */
2187 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2189 current_ir_graph = rem;
2192 /* dump iredges out edges */
2193 if ((flags & ir_dump_flag_iredges) && edges_activated(current_ir_graph)) {
2194 irg_walk_edges(get_irg_start_block(irg), dump_ir_edges, NULL, out);
2197 /* dump the out edges in a separate walk */
2198 if ((flags & ir_dump_flag_out_edges)
2199 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))) {
2200 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2203 dump_vcg_footer(out);
2206 static void dump_block_to_cfg(ir_node *block, void *env)
2208 FILE *F = (FILE*)env;
2211 if (is_Bad(block) && get_irn_mode(block) == mode_X) {
2212 dump_node(F, block);
2215 if (is_Block(block)) {
2216 /* This is a block. Dump a node for the block. */
2217 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2218 fprintf(F, "\" label: \"");
2219 if (block == get_irg_start_block(get_irn_irg(block)))
2220 fprintf(F, "Start ");
2221 if (block == get_irg_end_block(get_irn_irg(block)))
2224 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2225 PRINT_NODEID(block);
2227 fprintf(F, "info1:\"");
2229 /* the generic version. */
2230 dump_irnode_to_file(F, block);
2232 fprintf(F, "\""); /* closing quote of info */
2234 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2235 (block == get_irg_end_block(get_irn_irg(block))) )
2236 fprintf(F, " color:blue ");
2240 /* Dump the edges */
2241 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
2242 ir_node *pred = get_Block_cfgpred(block, i);
2244 pred = get_nodes_block(pred);
2245 fprintf(F, "edge: { sourcename: \"");
2246 PRINT_NODEID(block);
2247 fprintf(F, "\" targetname: \"");
2249 fprintf(F, "\"}\n");
2252 /* Dump dominator/postdominator edge */
2253 if (ir_get_dump_flags() & ir_dump_flag_dominance) {
2254 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_DOMINANCE) && get_Block_idom(block)) {
2255 ir_node *pred = get_Block_idom(block);
2256 fprintf(F, "edge: { sourcename: \"");
2257 PRINT_NODEID(block);
2258 fprintf(F, "\" targetname: \"");
2260 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2262 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE) && get_Block_ipostdom(block)) {
2263 ir_node *pred = get_Block_ipostdom(block);
2264 fprintf(F, "edge: { sourcename: \"");
2265 PRINT_NODEID(block);
2266 fprintf(F, "\" targetname: \"");
2268 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2274 void dump_cfg(FILE *F, ir_graph *irg)
2276 dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2278 /* walk over the blocks in the graph */
2279 irg_walk_graph(irg, dump_block_to_cfg, NULL, F);
2284 void dump_callgraph(FILE *F)
2287 ir_dump_flags_t old_flags = ir_get_dump_flags();
2289 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2290 dump_vcg_header(F, "Callgraph", "Hierarchic", NULL);
2292 for (i = get_irp_n_irgs(); i > 0;) {
2293 ir_graph *irg = get_irp_irg(--i);
2294 ir_entity *ent = get_irg_entity(irg);
2295 size_t j, n_callees = get_irg_n_callees(irg);
2297 dump_entity_node(F, ent);
2298 for (j = 0; j < n_callees; ++j) {
2299 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2300 int be = is_irg_callee_backedge(irg, j);
2301 const char *attr = be
2302 ? "label:\"recursion %zu\""
2303 : "label:\"calls %zu\"";
2304 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr,
2305 get_irg_callee_loop_depth(irg, j));
2309 ir_set_dump_flags(old_flags);
2313 void dump_typegraph(FILE *out)
2315 dump_vcg_header(out, "All_types", "Hierarchic", NULL);
2316 type_walk(dump_type_info, NULL, out);
2317 dump_vcg_footer(out);
2320 void dump_class_hierarchy(FILE *out)
2322 dump_vcg_header(out, "class_hierarchy", "Hierarchic", NULL);
2323 type_walk(dump_class_hierarchy_node, NULL, out);
2324 dump_vcg_footer(out);
2327 static void dump_loops_standalone(FILE *F, ir_loop *loop)
2330 bool loop_node_started = false;
2332 size_t son_number = 0;
2334 ir_loop *son = NULL;
2336 /* Dump a new loop node. */
2337 dump_loop_node(F, loop);
2339 /* Dump the loop elements. */
2340 for (i = 0; i < get_loop_n_elements(loop); i++) {
2341 le = get_loop_element(loop, i);
2343 if (get_kind(son) == k_ir_loop) {
2345 /* We are a loop son -> Recurse */
2347 if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2348 fprintf(F, "\" }\n");
2349 fprintf(F, "edge: {sourcename: \"");
2351 fprintf(F, "\" targetname: \"");
2353 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2354 (unsigned long) first,
2355 (unsigned long) first,
2356 (unsigned long) i-1);
2357 loop_node_started = false;
2359 dump_loop_son_edge(F, loop, son_number++);
2360 dump_loops_standalone(F, son);
2361 } else if (get_kind(son) == k_ir_node) {
2362 /* We are a loop node -> Collect firm nodes */
2364 ir_node *n = le.node;
2365 if (!loop_node_started) {
2366 /* Start a new node which contains all firm nodes of the current loop */
2367 fprintf(F, "node: { title: \"");
2369 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2371 loop_node_started = true;
2376 dump_node_label(F, n);
2377 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2378 if (has_backedges(n)) fprintf(F, "\t loop head!");
2379 } else { /* for callgraph loop tree */
2381 assert(get_kind(son) == k_ir_graph);
2383 /* We are a loop node -> Collect firm graphs */
2385 if (!loop_node_started) {
2386 /* Start a new node which contains all firm nodes of the current loop */
2387 fprintf(F, "node: { title: \"");
2389 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2391 loop_node_started = true;
2395 fprintf(F, " %s", get_irg_dump_name(n));
2396 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2400 if (loop_node_started) {
2401 fprintf(F, "\" }\n");
2402 fprintf(F, "edge: {sourcename: \"");
2404 fprintf(F, "\" targetname: \"");
2406 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2407 (unsigned long) first,
2408 (unsigned long) first,
2409 (unsigned long) i-1);
2410 loop_node_started = false;
2414 void dump_loop_tree(FILE *out, ir_graph *irg)
2416 ir_graph *rem = current_ir_graph;
2417 ir_dump_flags_t old_flags = ir_get_dump_flags();
2419 current_ir_graph = irg;
2420 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2422 dump_vcg_header(out, get_irg_dump_name(irg), "Tree", "top_to_bottom");
2424 if (get_irg_loop(irg))
2425 dump_loops_standalone(out, get_irg_loop(irg));
2427 dump_vcg_footer(out);
2429 ir_set_dump_flags(old_flags);
2430 current_ir_graph = rem;
2433 void dump_callgraph_loop_tree(FILE *out)
2435 dump_vcg_header(out, "callgraph looptree", "Tree", "top_to_bottom");
2436 dump_loops_standalone(out, irp->outermost_cg_loop);
2437 dump_vcg_footer(out);
2440 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
2444 int node_number = 0;
2446 if (flags & ir_dump_flag_loops)
2447 dump_loop_node(F, loop);
2449 for (i = 0; i < get_loop_n_elements(loop); i++) {
2450 loop_element le = get_loop_element(loop, i);
2451 if (*(le.kind) == k_ir_loop) {
2452 if (flags & ir_dump_flag_loops)
2453 dump_loop_son_edge(F, loop, son_number++);
2455 collect_nodeloop(F, le.son, loopnodes);
2457 if (flags & ir_dump_flag_loops)
2458 dump_loop_node_edge(F, loop, node_number++);
2459 eset_insert(loopnodes, le.node);
2464 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
2470 for (i = 0; i < get_loop_n_elements(loop); i++) {
2471 loop_element le = get_loop_element(loop, i);
2472 if (*(le.kind) == k_ir_loop) {
2474 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2476 if (is_Block(le.node)) start = 0; else start = -1;
2477 for (j = start; j < get_irn_arity(le.node); j++) {
2478 ir_node *pred = get_irn_n(le.node, j);
2479 if (!eset_contains(loopnodes, pred)) {
2480 eset_insert(extnodes, pred);
2481 if (!is_Block(pred)) {
2482 pred = get_nodes_block(pred);
2483 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2491 void dump_loop(FILE *F, ir_loop *l)
2493 eset *loopnodes = eset_create();
2494 eset *extnodes = eset_create();
2498 snprintf(name, sizeof(name), "loop_%ld", get_loop_loop_nr(l));
2499 dump_vcg_header(F, name, NULL, NULL);
2501 /* collect all nodes to dump */
2502 collect_nodeloop(F, l, loopnodes);
2503 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2505 /* build block lists */
2506 eset_foreach(loopnodes, ir_node*, n) {
2507 set_irn_link(n, NULL);
2509 eset_foreach(extnodes, ir_node*, n) {
2510 set_irn_link(n, NULL);
2512 eset_foreach(loopnodes, ir_node*, n) {
2514 b = get_nodes_block(n);
2515 set_irn_link(n, get_irn_link(b));
2519 eset_foreach(extnodes, ir_node*, n) {
2521 b = get_nodes_block(n);
2522 set_irn_link(n, get_irn_link(b));
2527 eset_foreach(loopnodes, ir_node*, b) {
2529 fprintf(F, "graph: { title: \"");
2531 fprintf(F, "\" label: \"");
2532 dump_node_opcode(F, b);
2533 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2534 fprintf(F, "\" status:clustered color:yellow\n");
2536 /* dump the blocks edges */
2537 dump_ir_data_edges(F, b);
2539 /* dump the nodes that go into the block */
2540 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2541 if (eset_contains(extnodes, n))
2542 overrule_nodecolor = ird_color_block_inout;
2544 overrule_nodecolor = ird_color_default_node;
2545 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2548 /* Close the vcg information for the block */
2550 dump_const_node_local(F, b);
2554 eset_foreach(extnodes, ir_node*, b) {
2556 fprintf(F, "graph: { title: \"");
2558 fprintf(F, "\" label: \"");
2559 dump_node_opcode(F, b);
2560 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2561 fprintf(F, "\" status:clustered color:lightblue\n");
2563 /* dump the nodes that go into the block */
2564 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2565 if (!eset_contains(loopnodes, n))
2566 overrule_nodecolor = ird_color_block_inout;
2568 overrule_nodecolor = ird_color_default_node;
2569 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2572 /* Close the vcg information for the block */
2574 dump_const_node_local(F, b);
2578 eset_destroy(loopnodes);
2579 eset_destroy(extnodes);
2584 static bool obstack_init;
2585 static struct obstack obst;
2586 static char *dump_path;
2588 void ir_set_dump_path(const char *path)
2591 dump_path = xstrdup(path);
2594 static void add_string_escaped(const char *string)
2597 for (p = string; *p != '\0'; ++p) {
2600 obstack_1grow(&obst, '@');
2601 obstack_1grow(&obst, '1');
2602 } else if (c == '@') {
2603 obstack_1grow(&obst, '@');
2604 obstack_1grow(&obst, '2');
2606 obstack_1grow(&obst, c);
2611 static void add_dump_path(void)
2613 if (!obstack_init) {
2614 obstack_init(&obst);
2615 obstack_init = true;
2618 if (dump_path != NULL) {
2619 size_t len = strlen(dump_path);
2620 obstack_grow(&obst, dump_path, len);
2621 if (len > 0 && dump_path[len-1] != '/')
2622 obstack_1grow(&obst, '/');
2626 void dump_ir_graph_ext(ir_graph_dump_func func, ir_graph *graph,
2629 const char *dump_name = get_irg_dump_name(graph);
2633 if (!ir_should_dump(dump_name))
2638 add_string_escaped(dump_name);
2639 obstack_printf(&obst, "-%02u", graph->dump_nr++);
2641 if (suffix != NULL) {
2642 if (suffix[0] != '.')
2643 obstack_1grow(&obst, '-');
2644 add_string_escaped(suffix);
2646 obstack_1grow(&obst, '\0');
2648 file_name = (char*)obstack_finish(&obst);
2649 /* xvcg expects only <CR> so we need "b"inary mode (for win32) */
2650 out = fopen(file_name, "wb");
2651 obstack_free(&obst, file_name);
2654 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2662 void dump_ir_prog_ext(ir_prog_dump_func func, const char *suffix)
2669 obstack_printf(&obst, "%02u", irp->dump_nr++);
2670 if (suffix != NULL) {
2671 if (suffix[0] != '.')
2672 obstack_1grow(&obst, '-');
2673 add_string_escaped(suffix);
2675 obstack_1grow(&obst, '\0');
2677 file_name = (char*)obstack_finish(&obst);
2678 out = fopen(file_name, "wb");
2679 obstack_free(&obst, file_name);
2682 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2689 void dump_ir_graph(ir_graph *graph, const char *suffix)
2693 snprintf(buf, sizeof(buf), "%s.vcg", suffix);
2694 dump_ir_graph_ext(dump_ir_graph_file, graph, buf);
2697 void dump_all_ir_graphs(const char *suffix)
2699 size_t i, n_irgs = get_irp_n_irgs();
2701 for (i = 0; i < n_irgs; ++i) {
2702 ir_graph *irg = get_irp_irg(i);
2703 dump_ir_graph(irg, suffix);
2707 typedef struct pass_t {
2708 ir_prog_pass_t pass;
2713 * Wrapper around dump_all_ir_graphs().
2715 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
2717 pass_t *pass = (pass_t*)context;
2720 dump_all_ir_graphs(pass->suffix);
2724 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name, const char *suffix)
2726 size_t len = strlen(suffix) + 1;
2727 pass_t *pass = XMALLOCF(pass_t, suffix, len);
2728 ir_prog_pass_t *res = def_prog_pass_constructor(
2729 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
2731 /* this pass does not change anything, so neither dump nor verify is needed. */
2732 res->dump_irprog = ir_prog_no_dump;
2733 res->verify_irprog = ir_prog_no_verify;
2735 memcpy(pass->suffix, suffix, len);