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 bool 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, const 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, const 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, const 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, const 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, const 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 void dump_node_label(FILE *F, const ir_node *n)
867 dump_node_opcode(F, n);
869 dump_node_mode(F, n);
871 dump_node_typeinfo(F, n);
872 dump_node_nodeattr(F, n);
873 if (flags & ir_dump_flag_number_label) {
874 fprintf(F, "%ld", get_irn_node_nr(n));
876 if (flags & ir_dump_flag_idx_label) {
877 fprintf(F, ":%u", get_irn_idx(n));
882 * Dumps the attributes of a node n into the file F.
883 * Currently this is only the color of a node.
885 static void dump_node_vcgattr(FILE *F, const ir_node *node, const ir_node *local, bool bad)
891 print_vcg_color(F, ird_color_error);
895 if (dump_node_vcgattr_hook != NULL) {
896 dump_node_vcgattr_hook(F, node, local);
900 n = local ? local : node;
902 if (overrule_nodecolor != ird_color_default_node) {
903 print_vcg_color(F, overrule_nodecolor);
907 mode = get_irn_mode(n);
908 if (mode == mode_M) {
909 print_vcg_color(F, ird_color_memory);
912 if (mode == mode_X) {
913 print_vcg_color(F, ird_color_controlflow);
917 switch (get_irn_opcode(n)) {
920 print_vcg_color(F, ird_color_anchor);
923 print_vcg_color(F, ird_color_error);
926 print_vcg_color(F, ird_color_block_background);
929 print_vcg_color(F, ird_color_phi);
932 print_vcg_color(F, ird_color_memory);
936 print_vcg_color(F, ird_color_const);
939 print_vcg_color(F, ird_color_proj);
942 ir_op *op = get_irn_op(node);
944 if (is_op_constlike(op)) {
945 print_vcg_color(F, ird_color_const);
946 } else if (is_op_uses_memory(op)) {
947 print_vcg_color(F, ird_color_uses_memory);
948 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
949 print_vcg_color(F, ird_color_controlflow);
955 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
957 hook_entry_t *info = XMALLOCZ(hook_entry_t);
959 info->hook._hook_node_info = cb;
960 info->context = data;
961 register_hook(hook_node_info, info);
966 void dump_remove_node_info_callback(void *handle)
968 hook_entry_t *info = (hook_entry_t*)handle;
969 unregister_hook(hook_node_info, info);
974 * Dump the node information of a node n to a file F.
976 static void dump_node_info(FILE *F, const ir_node *n)
978 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
980 fprintf(F, " info1: \"");
981 dump_irnode_to_file(F, n);
982 /* call the dump_node operation if available */
984 ops->dump_node(F, n, dump_node_info_txt);
986 /* allow additional info to be added */
987 hook_node_info(F, n);
991 static int is_constlike_node(const ir_node *node)
993 const ir_op *op = get_irn_op(node);
994 return is_op_constlike(op);
998 /** outputs the predecessors of n, that are constants, local. I.e.,
999 generates a copy of the constant predecessors for each node called with. */
1000 static void dump_const_node_local(FILE *F, const ir_node *n)
1003 if (!get_opt_dump_const_local()) return;
1005 /* Use visited flag to avoid outputting nodes twice.
1006 initialize it first. */
1007 for (i = 0; i < get_irn_arity(n); i++) {
1008 ir_node *con = get_irn_n(n, i);
1009 if (is_constlike_node(con)) {
1010 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
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) && !irn_visited_else_mark(con)) {
1017 /* Generate a new name for the node by appending the names of
1019 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1020 fprintf(F, " label: \"");
1021 dump_node_label(F, con);
1023 dump_node_info(F, con);
1024 dump_node_vcgattr(F, n, con, 0);
1030 /** If the block of an edge is a const_like node, dump it local with an edge */
1031 static void dump_const_block_local(FILE *F, const ir_node *n)
1035 if (!get_opt_dump_const_local()) return;
1037 blk = get_nodes_block(n);
1038 if (is_constlike_node(blk)) {
1039 /* Generate a new name for the node by appending the names of
1041 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1042 fprintf(F, "\" label: \"");
1043 dump_node_label(F, blk);
1045 dump_node_info(F, blk);
1046 dump_node_vcgattr(F, n, blk, 0);
1049 fprintf(F, "edge: { sourcename: \"");
1051 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1053 if (dump_edge_vcgattr_hook) {
1055 if (dump_edge_vcgattr_hook(F, n, -1)) {
1059 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1064 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1069 * prints the error message of a node to a file F as info2.
1071 static void print_node_error(FILE *F, const char *err_msg)
1076 fprintf(F, " info2: \"%s\"", err_msg);
1080 * prints debug messages of a node to file F as info3.
1082 static void print_dbg_info(FILE *F, dbg_info *dbg)
1086 ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1088 fprintf(F, " info3: \"%s\"\n", buf);
1092 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1102 void dump_node(FILE *F, const ir_node *n)
1107 if (get_opt_dump_const_local() && is_constlike_node(n))
1110 /* dump this node */
1111 fputs("node: {title: \"", F);
1115 fputs(" label: \"", F);
1116 bad = ! irn_verify_irg_dump(n, current_ir_graph, &p);
1117 dump_node_label(F, n);
1118 //dump_node_ana_info(F, n);
1121 if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1122 //fputs(" node_class:23", F);
1125 dump_node_info(F, n);
1126 print_node_error(F, p);
1127 print_dbg_info(F, get_irn_dbg_info(n));
1128 dump_node_vcgattr(F, n, NULL, bad);
1130 dump_const_node_local(F, n);
1134 /** dump the edge to the block this node belongs to */
1135 static void dump_ir_block_edge(FILE *F, const ir_node *n)
1137 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1139 ir_node *block = get_nodes_block(n);
1141 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1142 dump_const_block_local(F, n);
1144 fprintf(F, "edge: { sourcename: \"");
1146 fprintf(F, "\" targetname: ");
1147 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1149 if (dump_edge_vcgattr_hook) {
1151 if (dump_edge_vcgattr_hook(F, n, -1)) {
1155 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1160 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1165 static void print_data_edge_vcgattr(FILE *F, const ir_node *from, int to)
1168 * do not use get_nodes_block() here, will fail
1169 * if the irg is not pinned.
1171 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1172 fprintf(F, INTRA_DATA_EDGE_ATTR);
1174 fprintf(F, INTER_DATA_EDGE_ATTR);
1177 static void print_mem_edge_vcgattr(FILE *F, const ir_node *from, int to)
1180 * do not use get_nodes_block() here, will fail
1181 * if the irg is not pinned.
1183 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1184 fprintf(F, INTRA_MEM_EDGE_ATTR);
1186 fprintf(F, INTER_MEM_EDGE_ATTR);
1189 /** Print the vcg attributes for the edge from node "from" to its "to"th input */
1190 static void print_edge_vcgattr(FILE *F, const ir_node *from, int to)
1194 if (dump_edge_vcgattr_hook)
1195 if (dump_edge_vcgattr_hook(F, from, to))
1198 if ((flags & ir_dump_flag_back_edges) && is_backedge(from, to))
1199 fprintf(F, BACK_EDGE_ATTR);
1201 switch (get_irn_opcode(from)) {
1203 fprintf(F, CF_EDGE_ATTR);
1205 case iro_Start: break;
1208 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1209 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1211 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1215 if (is_Proj(from)) {
1216 if (get_irn_mode(from) == mode_M)
1217 print_mem_edge_vcgattr(F, from, to);
1218 else if (get_irn_mode(from) == mode_X)
1219 fprintf(F, CF_EDGE_ATTR);
1221 print_data_edge_vcgattr(F, from, to);
1223 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1224 print_mem_edge_vcgattr(F, from, to);
1225 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1226 fprintf(F, CF_EDGE_ATTR);
1228 print_data_edge_vcgattr(F, from, to);
1232 /** dump edges to our inputs */
1233 static void dump_ir_data_edges(FILE *F, const ir_node *n)
1237 if (dump_node_edge_hook)
1238 dump_node_edge_hook(F, n);
1240 if (!(flags & ir_dump_flag_keepalive_edges) && is_End(n)) {
1241 /* the End node has only keep-alive edges */
1245 /* dump the dependency edges. */
1246 num = get_irn_deps(n);
1247 for (i = 0; i < num; ++i) {
1248 ir_node *dep = get_irn_dep(n, i);
1251 print_node_edge_kind(F, n);
1252 fprintf(F, "{sourcename: \"");
1254 fprintf(F, "\" targetname: ");
1255 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1256 PRINT_CONSTID(n, dep);
1262 fprintf(F, " label: \"%d\" ", i);
1263 fprintf(F, " color: darkgreen}\n");
1267 num = get_irn_arity(n);
1268 for (i = 0; i < num; i++) {
1269 ir_node *pred = get_irn_n(n, i);
1272 if ((flags & ir_dump_flag_back_edges) && is_backedge(n, i)) {
1273 fprintf(F, "backedge: {sourcename: \"");
1275 print_node_edge_kind(F, n);
1276 fprintf(F, "{sourcename: \"");
1279 fprintf(F, "\" targetname: ");
1280 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1281 PRINT_CONSTID(n, pred);
1283 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1285 fprintf(F, " label: \"%d\" ", i);
1286 print_edge_vcgattr(F, n, i);
1294 static void dump_ir_edges(ir_node *node, void *env)
1297 FILE *F = (FILE*)env;
1298 const ir_edge_t *edge;
1300 foreach_out_edge(node, edge) {
1301 ir_node *succ = get_edge_src_irn(edge);
1303 print_node_edge_kind(F, succ);
1304 fprintf(F, "{sourcename: \"");
1306 fprintf(F, "\" targetname: \"");
1310 fprintf(F, " label: \"%d\" ", i);
1311 fprintf(F, OUT_EDGE_ATTR);
1318 /** Dumps a node and its edges but not the block edge */
1319 static void dump_node_wo_blockedge(FILE *F, const ir_node *n)
1322 dump_ir_data_edges(F, n);
1325 /** Dumps a node and its edges. */
1326 static void dump_node_with_edges(ir_node *n, void *env)
1328 FILE *F = (FILE*)env;
1329 dump_node_wo_blockedge(F, n);
1330 if (!node_floats(n))
1331 dump_ir_block_edge(F, n);
1334 /** Dumps a const-like node. */
1335 static void dump_const_node(ir_node *n, void *env)
1337 FILE *F = (FILE*)env;
1338 if (is_Block(n)) return;
1339 dump_node_wo_blockedge(F, n);
1342 /***********************************************************************/
1343 /* the following routines dump the nodes/irgs bracketed to graphs. */
1344 /***********************************************************************/
1346 /** Dumps a constant expression as entity initializer, array bound ... */
1347 static void dump_const_expression(FILE *F, ir_node *value)
1349 ir_graph *rem = current_ir_graph;
1350 ir_dump_flags_t old_flags = ir_get_dump_flags();
1351 ir_remove_dump_flags(ir_dump_flag_consts_local);
1353 current_ir_graph = get_const_code_irg();
1354 irg_walk(value, dump_const_node, NULL, F);
1355 /* Decrease visited flag so that we walk with the same flag for the next
1356 expression. This guarantees that we don't dump the same node twice,
1357 as for const expressions cse is performed to save memory. */
1358 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1360 ir_set_dump_flags(old_flags);
1361 current_ir_graph = rem;
1364 /** Dump a block as graph containing its nodes.
1366 * Expects to find nodes belonging to the block as list in its
1368 * Dumps the edges of all nodes including itself. */
1369 static void dump_whole_block(FILE *F, const ir_node *block)
1372 ird_color_t color = ird_color_block_background;
1374 assert(is_Block(block));
1376 fprintf(F, "graph: { title: \"");
1377 PRINT_NODEID(block);
1378 fprintf(F, "\" label: \"");
1379 dump_node_label(F, block);
1381 /* colorize blocks */
1382 if (! get_Block_matured(block))
1383 color = ird_color_block_background;
1385 fprintf(F, "\" status:clustered ");
1386 print_vcg_color(F, color);
1389 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1390 dump_node_info(F, block);
1391 print_dbg_info(F, get_irn_dbg_info(block));
1393 /* dump the blocks edges */
1394 dump_ir_data_edges(F, block);
1396 if (dump_block_edge_hook)
1397 dump_block_edge_hook(F, block);
1399 /* dump the nodes that go into the block */
1400 for (node = (ir_node*)ird_get_irn_link(block); node; node = (ir_node*)ird_get_irn_link(node)) {
1402 dump_ir_data_edges(F, node);
1405 /* Close the vcg information for the block */
1407 dump_const_node_local(F, block);
1411 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1412 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1413 static void dump_block_graph(FILE *F, ir_graph *irg)
1416 ir_graph *rem = current_ir_graph;
1417 ir_node **arr = (ir_node**)ird_get_irg_link(irg);
1418 current_ir_graph = irg;
1420 for (i = 0, n = ARR_LEN(arr); i < n; ++i) {
1421 ir_node *node = arr[i];
1422 if (is_Block(node)) {
1423 /* Dumps the block and all the nodes in the block, which are to
1424 be found in Block->link. */
1425 dump_whole_block(F, node);
1427 /* Nodes that are not in a Block. */
1429 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1430 dump_const_block_local(F, node);
1432 dump_ir_data_edges(F, node);
1434 if ((flags & ir_dump_flag_iredges) && edges_activated(irg))
1435 dump_ir_edges(node, F);
1438 if ((flags & ir_dump_flag_loops)
1439 && is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1440 dump_loop_nodes_into_graph(F, irg);
1442 current_ir_graph = rem;
1446 * Dump the info for an irg.
1447 * Parsed by XVCG but not shown. use yComp.
1449 static void dump_graph_info(FILE *F, ir_graph *irg)
1451 fprintf(F, "info1: \"");
1452 dump_entity_to_file(F, get_irg_entity(irg));
1455 /* dump graph state */
1456 fprintf(F, "state:");
1457 if (is_irg_state(irg, IR_GRAPH_STATE_ARCH_DEP))
1458 fprintf(F, " arch_dep");
1459 if (is_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED))
1460 fprintf(F, " modeb_lowered");
1461 if (is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
1462 fprintf(F, " normalisation2");
1463 if (is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING))
1464 fprintf(F, " implicit_bitfield_masking");
1465 if (is_irg_state(irg, IR_GRAPH_STATE_OPTIMIZE_UNREACHABLE_CODE))
1466 fprintf(F, " optimize_unreachable_code");
1467 if (is_irg_state(irg, IR_GRAPH_STATE_NO_CRITICAL_EDGES))
1468 fprintf(F, " no_critical_edges");
1469 if (is_irg_state(irg, IR_GRAPH_STATE_NO_BADS))
1470 fprintf(F, " no_bads");
1471 if (is_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE))
1472 fprintf(F, " no_unreachable_code");
1473 if (is_irg_state(irg, IR_GRAPH_STATE_ONE_RETURN))
1474 fprintf(F, " one_return");
1475 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE))
1476 fprintf(F, " consistent_dominance");
1477 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE))
1478 fprintf(F, " consistent_postdominance");
1479 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUT_EDGES))
1480 fprintf(F, " consistent_out_edges");
1481 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))
1482 fprintf(F, " consistent_outs");
1483 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1484 fprintf(F, " consistent_loopinfo");
1485 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE))
1486 fprintf(F, " consistent_entity_usage");
1487 if (is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
1488 fprintf(F, " valid_exended_blocks");
1492 /** Dumps an irg as a graph clustered by block nodes.
1493 * If interprocedural view edges can point to nodes out of this graph.
1495 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1497 ir_entity *ent = get_irg_entity(irg);
1499 fprintf(F, "graph: { title: \"");
1501 fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1502 get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1504 dump_graph_info(F, irg);
1505 print_dbg_info(F, get_entity_dbg_info(ent));
1507 dump_block_graph(F, irg);
1509 /* Close the vcg information for the irg */
1510 fprintf(F, "}\n\n");
1513 /*******************************************************************/
1514 /* Basic type and entity nodes and edges. */
1515 /*******************************************************************/
1517 /** dumps the edges between nodes and their type or entity attributes. */
1518 static void dump_node2type_edges(ir_node *n, void *env)
1520 FILE *F = (FILE*)env;
1523 switch (get_irn_opcode(n)) {
1525 /* @@@ some consts have an entity */
1528 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1529 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1532 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1535 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1538 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1541 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1544 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1552 static int print_type_info(FILE *F, ir_type *tp)
1556 if (get_type_state(tp) == layout_undefined) {
1557 fprintf(F, "state: layout_undefined\n");
1559 fprintf(F, "state: layout_fixed,\n");
1561 if (get_type_mode(tp))
1562 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1563 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1568 static void print_typespecific_info(FILE *F, ir_type *tp)
1570 switch (get_type_tpop_code(tp)) {
1572 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1577 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1578 fprintf(F, "params: %d\n", get_method_n_params(tp));
1579 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1585 case tpo_enumeration:
1597 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
1599 switch (get_type_tpop_code(tp)) {
1601 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1604 fprintf(F, " " TYPE_METH_NODE_ATTR);
1612 case tpo_enumeration:
1623 void dump_type_node(FILE *F, ir_type *tp)
1625 fprintf(F, "node: {title: ");
1627 fprintf(F, " label: \"");
1628 if (tp->dbi != NULL) {
1630 ir_print_type(buf, sizeof(buf), tp);
1631 fprintf(F, "%s '%s'", get_type_tpop_name(tp), buf);
1633 ir_fprintf(F, "%+F", tp);
1635 fputs("\" info1: \"", F);
1636 dump_type_to_file(F, tp);
1638 print_type_dbg_info(F, get_type_dbg_info(tp));
1639 print_typespecific_vcgattr(F, tp);
1643 static void dump_entity_node(FILE *F, ir_entity *ent)
1645 fprintf(F, "node: {title: \"");
1646 PRINT_ENTID(ent); fprintf(F, "\"");
1647 fprintf(F, " label: ");
1648 fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
1650 print_vcg_color(F, ird_color_entity);
1651 fprintf(F, "\n info1: \"");
1653 dump_entity_to_file(F, ent);
1656 print_dbg_info(F, get_entity_dbg_info(ent));
1660 static void dump_enum_item(FILE *F, ir_type *tp, size_t pos)
1663 ir_enum_const *ec = get_enumeration_const(tp, pos);
1664 ident *id = get_enumeration_const_nameid(ec);
1665 ir_tarval *tv = get_enumeration_value(ec);
1668 tarval_snprintf(buf, sizeof(buf), tv);
1670 strncpy(buf, "<not set>", sizeof(buf));
1671 fprintf(F, "node: {title: \"");
1672 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1673 fprintf(F, " label: ");
1674 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1675 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1679 * Dumps a new style initializer.
1681 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
1689 * type-walker: Dumps a type or entity and its edges.
1691 static void dump_type_info(type_or_ent tore, void *env)
1693 FILE *F = (FILE*)env;
1694 size_t i = 0; /* to shutup gcc */
1696 /* dump this type or entity */
1698 switch (get_kind(tore.ent)) {
1700 ir_entity *ent = tore.ent;
1703 dump_entity_node(F, ent);
1705 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1706 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1707 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1708 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1709 if (is_Class_type(get_entity_owner(ent))) {
1710 for (i = get_entity_n_overwrites(ent); i > 0;)
1711 print_ent_ent_edge(F, ent, get_entity_overwrites(ent, --i), 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1713 /* attached subgraphs */
1714 if (! (flags & ir_dump_flag_no_entity_values)) {
1715 if (ent->initializer != NULL) {
1716 /* new style initializers */
1717 dump_entity_initializer(F, ent);
1718 } else if (entity_has_compound_ent_values(ent)) {
1719 /* old style compound entity values */
1720 for (i = get_compound_ent_n_values(ent); i > 0;) {
1721 value = get_compound_ent_value(ent, --i);
1723 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1724 dump_const_expression(F, value);
1725 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ird_color_none, ENT_CORR_EDGE_ATTR, i);
1727 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1728 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1729 get_compound_ent_value_member(ent, i), i);
1738 ir_type *tp = tore.typ;
1739 dump_type_node(F, tp);
1740 /* and now the edges */
1741 switch (get_type_tpop_code(tp)) {
1743 for (i = get_class_n_supertypes(tp); i > 0;) {
1745 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
1747 for (i = get_class_n_members(tp); i > 0;) {
1749 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1753 for (i = get_struct_n_members(tp); i > 0;) {
1755 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1759 for (i = get_method_n_params(tp); i > 0;) {
1761 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
1763 for (i = get_method_n_ress(tp); i > 0;) {
1765 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
1769 for (i = get_union_n_members(tp); i > 0;) {
1771 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
1775 print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
1776 print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
1777 for (i = get_array_n_dimensions(tp); i > 0;) {
1778 ir_node *upper, *lower;
1781 upper = get_array_upper_bound(tp, i);
1782 lower = get_array_lower_bound(tp, i);
1783 print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
1784 print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
1785 dump_const_expression(F, upper);
1786 dump_const_expression(F, lower);
1789 case tpo_enumeration:
1790 for (i = get_enumeration_n_enums(tp); i > 0;) {
1792 dump_enum_item(F, tp, i);
1793 print_enum_item_edge(F, tp, i, "label: \"item %zu\"", i);
1797 print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1804 break; /* case k_type */
1807 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1811 /** For dumping class hierarchies.
1812 * Dumps a class type node and a superclass edge.
1814 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
1816 FILE *F = (FILE*)ctx;
1817 size_t i = 0; /* to shutup gcc */
1819 /* dump this type or entity */
1820 switch (get_kind(tore.ent)) {
1822 ir_entity *ent = tore.ent;
1823 if (get_entity_owner(ent) == get_glob_type()) break;
1824 if (!is_Method_type(get_entity_type(ent)))
1826 if (flags & ir_dump_flag_entities_in_hierarchy
1827 && is_Class_type(get_entity_owner(ent))) {
1829 dump_entity_node(F, ent);
1831 print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
1832 for (i = get_entity_n_overwrites(ent); i > 0;) {
1834 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1840 ir_type *tp = tore.typ;
1841 if (tp == get_glob_type())
1843 switch (get_type_tpop_code(tp)) {
1845 dump_type_node(F, tp);
1846 /* and now the edges */
1847 for (i = get_class_n_supertypes(tp); i > 0;) {
1849 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1854 break; /* case k_type */
1857 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1861 /*******************************************************************/
1862 /* dump analysis information that is expressed in graph terms. */
1863 /*******************************************************************/
1865 /* dump out edges */
1866 static void dump_out_edge(ir_node *n, void *env)
1868 FILE *F = (FILE*)env;
1870 for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
1871 ir_node *succ = get_irn_out(n, i);
1873 print_node_edge_kind(F, succ);
1874 fprintf(F, "{sourcename: \"");
1876 fprintf(F, "\" targetname: \"");
1878 fprintf(F, "\" color: red linestyle: dashed");
1883 static void dump_loop_label(FILE *F, const ir_loop *loop)
1885 fprintf(F, "loop %u", get_loop_depth(loop));
1888 static void dump_loop_info(FILE *F, const ir_loop *loop)
1890 fprintf(F, " info1: \"");
1891 fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
1892 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
1893 fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
1898 static void dump_loop_node(FILE *F, const ir_loop *loop)
1900 fprintf(F, "node: {title: \"");
1902 fprintf(F, "\" label: \"");
1903 dump_loop_label(F, loop);
1905 dump_loop_info(F, loop);
1909 static void dump_loop_node_edge(FILE *F, const ir_loop *loop, size_t i)
1912 fprintf(F, "edge: {sourcename: \"");
1914 fprintf(F, "\" targetname: \"");
1915 PRINT_NODEID(get_loop_element(loop, i).node);
1916 fprintf(F, "\" color: green");
1920 static void dump_loop_son_edge(FILE *F, const ir_loop *loop, size_t i)
1923 fprintf(F, "edge: {sourcename: \"");
1925 fprintf(F, "\" targetname: \"");
1926 PRINT_LOOPID(get_loop_element(loop, i).son);
1927 ir_fprintf(F, "\" color: darkgreen label: \"%zu\"}\n", i);
1930 static void dump_loops(FILE *F, const ir_loop *loop)
1933 size_t n_elements = get_loop_n_elements(loop);
1934 /* dump this loop node */
1935 dump_loop_node(F, loop);
1937 /* dump edges to nodes in loop -- only if it is a real loop */
1938 if (get_loop_depth(loop) != 0) {
1939 for (i = n_elements; i > 0;) {
1940 loop_element element;
1942 element = get_loop_element(loop, i);
1943 if (*element.kind != k_ir_node)
1945 dump_loop_node_edge(F, loop, i);
1948 for (i = n_elements; i > 0;) {
1949 loop_element element;
1951 element = get_loop_element(loop, i);
1952 if (*element.kind != k_ir_loop)
1954 dump_loops(F, element.son);
1955 dump_loop_son_edge(F, loop, i);
1959 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
1961 ir_loop *loop = get_irg_loop(irg);
1964 ir_graph *rem = current_ir_graph;
1965 current_ir_graph = irg;
1967 dump_loops(F, loop);
1969 current_ir_graph = rem;
1973 void dump_vcg_header_colors(FILE *F)
1977 for (i = 0; i < ird_color_count; ++i) {
1978 if (color_rgb[i] != NULL) {
1979 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
1984 void dump_vcg_infonames(FILE *F)
1987 "infoname 1: \"Attribute\"\n"
1988 "infoname 2: \"Verification errors\"\n"
1989 "infoname 3: \"Debug info\"\n", F);
1993 * dumps the VCG header
1995 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";
2000 if (! layout) layout = "Compilergraph";
2001 if (!orientation) orientation = "bottom_to_top";
2005 "graph: { title: \"ir graph of %s\"\n"
2006 "display_edge_labels: %s\n"
2007 "layoutalgorithm: mindepth //$ \"%s\"\n"
2008 "manhattan_edges: yes\n"
2009 "port_sharing: no\n"
2011 "classname 1: \"intrablock Data\"\n"
2012 "classname 2: \"Block\"\n"
2013 "classname 3: \"Entity type\"\n"
2014 "classname 4: \"Entity owner\"\n"
2015 "classname 5: \"Method Param\"\n"
2016 "classname 6: \"Method Res\"\n"
2017 "classname 7: \"Super\"\n"
2018 "classname 8: \"Union\"\n"
2019 "classname 9: \"Points-to\"\n"
2020 "classname 10: \"Array Element Type\"\n"
2021 "classname 11: \"Overwrites\"\n"
2022 "classname 12: \"Member\"\n"
2023 "classname 13: \"Control Flow\"\n"
2024 "classname 14: \"intrablock Memory\"\n"
2025 "classname 15: \"Dominators\"\n"
2026 "classname 16: \"interblock Data\"\n"
2027 "classname 17: \"interblock Memory\"\n"
2028 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2029 "classname 19: \"Postdominators\"\n"
2030 "classname 20: \"Keep Alive\"\n"
2031 "classname 21: \"Out Edges\"\n"
2032 "classname 22: \"Macro Block Edges\"\n",
2033 name, label, layout, orientation);
2034 dump_vcg_infonames(F);
2035 dump_vcg_header_colors(F);
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);