2 * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Write vcg representation of firm to file.
23 * @author Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt,
38 #include "irgraph_t.h"
52 #include "callgraph.h"
53 #include "irextbb_t.h"
55 #include "dbginfo_t.h"
69 /** Dump only irgs with names that start with this prefix. */
70 static ident *dump_file_filter_id = NULL;
72 static ir_dump_flags_t flags =
73 ir_dump_flag_blocks_as_subgraphs |
74 ir_dump_flag_keepalive_edges |
75 ir_dump_flag_ld_names |
76 ir_dump_flag_back_edges |
77 ir_dump_flag_consts_local |
78 ir_dump_flag_analysed_types |
79 ir_dump_flag_entities_in_hierarchy |
80 ir_dump_flag_number_label;
82 static ird_color_t overrule_nodecolor = ird_color_default_node;
84 /** The vcg node attribute hook. */
85 static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
86 /** The vcg edge attribute hook. */
87 static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
88 /** The vcg dump block edge hook */
89 static dump_node_edge_func dump_block_edge_hook = NULL;
90 /** The vcg dump node edge hook. */
91 static dump_node_edge_func dump_node_edge_hook = NULL;
93 void set_dump_node_edge_hook(dump_node_edge_func func)
95 dump_node_edge_hook = func;
98 dump_node_edge_func get_dump_node_edge_hook(void)
100 return dump_node_edge_hook;
103 void set_dump_block_edge_hook(dump_node_edge_func func)
105 dump_block_edge_hook = func;
108 dump_node_edge_func get_dump_block_edge_hook(void)
110 return dump_node_edge_hook;
113 void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
115 dump_node_vcgattr_hook = hook;
118 void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
120 dump_edge_vcgattr_hook = hook;
123 void ir_set_dump_flags(ir_dump_flags_t new_flags)
128 void ir_add_dump_flags(ir_dump_flags_t new_flags)
133 void ir_remove_dump_flags(ir_dump_flags_t to_remove)
138 ir_dump_flags_t ir_get_dump_flags(void)
143 /** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
144 * are set, else returns dump_const_local_flag.
146 static bool get_opt_dump_const_local(void)
148 return (flags & ir_dump_flag_out_edges)
149 || (flags & ir_dump_flag_loops)
150 || (flags & ir_dump_flag_consts_local)
151 || (flags & ir_dump_flag_iredges);
154 static char *dump_filter;
156 void ir_set_dump_filter(const char *new_filter)
159 dump_filter = xstrdup(new_filter);
162 const char *ir_get_dump_filter(void)
167 int ir_should_dump(const char *name)
171 if (dump_filter == NULL || dump_filter[0] == '\0')
174 for (n = name, f = dump_filter; *f != '\0' && *n != '\0';
182 /* -------------- some extended helper functions ----------------- */
184 const char *get_mode_name_ex(const ir_mode *mode, int *bad)
187 return get_mode_name(mode);
193 #define CUSTOM_COLOR_BASE 100
194 static const char *color_names[ird_color_count];
195 static const char *color_rgb[ird_color_count];
196 static struct obstack color_obst;
198 /** define a custom color. */
199 static void custom_color(int num, const char *rgb_def)
201 assert(num < ird_color_count);
202 obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
203 obstack_1grow(&color_obst, '\0');
205 color_rgb[num] = rgb_def;
206 color_names[num] = (const char*)obstack_finish(&color_obst);
209 /** Define a named color. */
210 static void named_color(int num, const char *name)
212 assert(num < ird_color_count);
213 color_rgb[num] = NULL;
214 color_names[num] = name;
217 /** Initializes the used colors. */
218 static void init_colors(void)
220 static int initialized = 0;
224 obstack_init(&color_obst);
226 custom_color(ird_color_prog_background, "204 204 204");
227 custom_color(ird_color_block_background, "255 255 0");
228 custom_color(ird_color_dead_block_background, "190 150 150");
229 named_color(ird_color_block_inout, "lightblue");
230 named_color(ird_color_default_node, "white");
231 custom_color(ird_color_memory, "153 153 255");
232 custom_color(ird_color_controlflow, "255 153 153");
233 custom_color(ird_color_const, "204 255 255");
234 custom_color(ird_color_proj, "255 255 153");
235 custom_color(ird_color_uses_memory, "153 153 255");
236 custom_color(ird_color_phi, "105 255 105");
237 custom_color(ird_color_anchor, "100 100 255");
238 named_color(ird_color_error, "red");
239 custom_color(ird_color_entity, "204 204 255");
245 * Prints the VCG color to a file.
247 static void print_vcg_color(FILE *out, ird_color_t color)
249 assert(color < ird_color_count);
250 fprintf(out, "color:%s", color_names[color]);
254 * Prints the edge kind of a given IR node.
256 * Projs should be dumped near their predecessor, so they get "nearedge".
258 static void print_node_edge_kind(FILE *out, ir_node *node)
261 fprintf(out, "nearedge: ");
263 fprintf(out, "edge: ");
268 * Prints the edge from a type S to a type T with additional info fmt, ...
271 static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
276 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
277 fprintf(F, " targetname: "); PRINT_TYPEID(T);
278 ir_vfprintf(F, fmt, ap);
284 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
287 static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
292 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
293 fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
294 ir_vfprintf(F, fmt, ap);
300 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
303 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, ...)
309 fprintf(F, "backedge: { sourcename: \"");
311 fprintf(F, "edge: { sourcename: \"");
313 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2); fprintf(F, "\"");
314 ir_vfprintf(F, fmt, ap);
316 if (color != ird_color_none)
317 print_vcg_color(F, color);
323 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
326 static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
331 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
332 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
333 ir_vfprintf(F, fmt, ap);
339 * Prints the edge from a node irn to a type tp with additional info fmt, ...
342 static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
347 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
348 fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
349 ir_vfprintf(F, fmt, ap);
355 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
358 static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
363 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
364 fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
366 ir_vfprintf(F, fmt, ap);
372 * Prints the edge from an entity ent to a node irn with additional info fmt, ...
375 static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
380 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
381 fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
382 ir_vfprintf(F, fmt, ap);
388 * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
391 static void print_enum_item_edge(FILE *F, const ir_type *tp, size_t item, const char *fmt, ...)
396 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
397 fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
398 ir_vfprintf(F, fmt, ap);
403 /*-----------------------------------------------------------------*/
404 /* global and ahead declarations */
405 /*-----------------------------------------------------------------*/
407 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
409 /*-----------------------------------------------------------------*/
410 /* Helper functions. */
411 /*-----------------------------------------------------------------*/
414 * This map is used as a private link attr to be able to call dumper
415 * anywhere without destroying link fields.
417 static pmap *irdump_link_map = NULL;
419 /** NOT A STANDARD LIBFIRM INIT METHOD
421 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
422 * are off, we want to have as few interferences as possible. Therefore the
423 * initialization is performed lazily and not called from within init_firm.
425 * Creates the link attribute map. */
426 static void init_irdump(void)
428 /* We need a new, empty map. */
429 if (irdump_link_map) pmap_destroy(irdump_link_map);
430 irdump_link_map = pmap_create();
431 if (!dump_file_filter_id)
432 dump_file_filter_id = new_id_from_str("");
436 * Returns the private link field.
438 static void *ird_get_irn_link(const ir_node *n)
441 if (irdump_link_map == NULL)
444 if (pmap_contains(irdump_link_map, n))
445 res = pmap_get(irdump_link_map, n);
450 * Sets the private link field.
452 static void ird_set_irn_link(const ir_node *n, void *x)
454 if (irdump_link_map == NULL)
456 pmap_insert(irdump_link_map, n, x);
460 * Gets the private link field of an irg.
462 static void *ird_get_irg_link(const ir_graph *irg)
465 if (irdump_link_map == NULL)
468 if (pmap_contains(irdump_link_map, irg))
469 res = pmap_get(irdump_link_map, irg);
474 * Sets the private link field of an irg.
476 static void ird_set_irg_link(const ir_graph *irg, void *x)
478 if (irdump_link_map == NULL)
480 pmap_insert(irdump_link_map, irg, x);
484 * Walker, clears the private link field.
486 static void clear_link(ir_node *node, void *env)
489 ird_set_irn_link(node, NULL);
493 * If the entity has a ld_name, returns it if the dump_ld_name is set,
494 * else returns the name of the entity.
496 static const char *_get_ent_dump_name(const ir_entity *ent, bool dump_ld_name)
499 return "<NULL entity>";
501 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
502 if (ent->ld_name != NULL)
503 return get_id_str(ent->ld_name);
505 return get_id_str(ent->name);
508 const char *get_ent_dump_name(const ir_entity *ent)
510 return _get_ent_dump_name(ent, flags & ir_dump_flag_ld_names);
513 const char *get_irg_dump_name(const ir_graph *irg)
515 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
516 return _get_ent_dump_name(get_irg_entity(irg), true);
520 * Returns non-zero if a node is in floating state.
522 static int node_floats(const ir_node *n)
524 return ((get_irn_pinned(n) == op_pin_state_floats) &&
525 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
529 * Walker that visits the anchors
531 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
533 if ((flags & ir_dump_flag_all_anchors)
534 || ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
535 irg_walk_anchors(irg, pre, post, env);
537 irg_walk_graph(irg, pre, post, env);
542 * Walker, allocates an array for all blocks and puts their non-floating
543 * nodes into this array.
545 static void collect_node(ir_node *node, void *env)
550 || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
551 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
552 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
553 ARR_APP1(ir_node *, arr, node);
554 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
556 ir_node * block = get_nodes_block(node);
559 /* this node is in a Bad block, so we must place it into the graph's list */
560 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
561 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
562 ARR_APP1(ir_node *, arr, node);
563 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
565 ird_set_irn_link(node, ird_get_irn_link(block));
566 ird_set_irn_link(block, node);
571 /** Construct lists to walk ir block-wise.
573 * Collects all blocks, nodes not op_pin_state_pinned,
574 * Bad, NoMem and Unknown into a flexible array in link field of
575 * irg they belong to. Sets the irg link field to NULL in all
576 * graphs not visited.
577 * Free the list with DEL_ARR_F().
579 static ir_node **construct_block_lists(ir_graph *irg)
582 int walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
583 ir_graph *rem = current_ir_graph;
585 current_ir_graph = irg;
588 ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
591 for (i = get_irp_n_irgs(); i > 0;)
592 ird_set_irg_link(get_irp_irg(--i), NULL);
594 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
597 ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
600 current_ir_graph = rem;
601 return (ir_node**)ird_get_irg_link(irg);
604 typedef struct list_tuple {
606 ir_extblk **extbb_list;
609 /** Construct lists to walk IR extended block-wise.
610 * Free the lists in the tuple with DEL_ARR_F(). Sets the irg link field to
611 * NULL in all graphs not visited.
613 static list_tuple *construct_extblock_lists(ir_graph *irg)
615 ir_node **blk_list = construct_block_lists(irg);
617 ir_graph *rem = current_ir_graph;
618 list_tuple *lists = XMALLOC(list_tuple);
620 current_ir_graph = irg;
622 lists->blk_list = NEW_ARR_F(ir_node *, 0);
623 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
625 inc_irg_block_visited(irg);
626 for (i = 0, n = ARR_LEN(blk_list); i < n; ++i) {
629 if (is_Block(blk_list[i])) {
630 ext = get_Block_extbb(blk_list[i]);
632 if (extbb_not_visited(ext)) {
633 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
634 mark_extbb_visited(ext);
637 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
641 current_ir_graph = rem;
642 ird_set_irg_link(irg, lists);
646 void dump_node_opcode(FILE *F, ir_node *n)
648 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
650 /* call the dump_node operation if available */
651 if (ops->dump_node) {
652 ops->dump_node(F, n, dump_node_opcode_txt);
656 /* implementation for default nodes */
657 switch (get_irn_opcode(n)) {
659 switch (get_SymConst_kind(n)) {
660 case symconst_addr_ent:
661 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
663 case symconst_ofs_ent:
664 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
666 case symconst_type_tag:
667 ir_fprintf(F, "SymC %+F tag", get_SymConst_type(n));
669 case symconst_type_size:
670 ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
672 case symconst_type_align:
673 ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
675 case symconst_enum_const:
676 fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
682 ir_node *pred = get_Proj_pred(n);
684 if (get_irn_opcode(pred) == iro_Cond
685 && get_Proj_proj(n) == get_Cond_default_proj(pred)
686 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
687 fprintf(F, "defProj");
693 if (get_Load_unaligned(n) == align_non_aligned)
695 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), NULL));
698 if (get_Store_unaligned(n) == align_non_aligned)
700 fprintf(F, "%s", get_irn_opname(n));
703 if (n == get_irg_start_block(get_irn_irg(n)))
705 if (n == get_irg_end_block(get_irn_irg(n)))
707 fprintf(F, "%s%s", get_irn_opname(n),
708 (flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
711 if (get_Conv_strict(n))
712 fprintf(F, "strict");
713 fprintf(F, "%s", get_irn_opname(n));
716 fprintf(F, "%s", get_irn_opname(n));
717 if (get_Div_no_remainder(n))
719 fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), NULL));
722 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), NULL));
725 fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
730 fprintf(F, "%s", get_irn_opname(n));
735 * Dump the mode of a node n to a file F.
736 * Ignore modes that are "always known".
738 static void dump_node_mode(FILE *F, ir_node *n)
740 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
744 /* call the dump_node operation if available */
745 if (ops->dump_node) {
746 ops->dump_node(F, n, dump_node_mode_txt);
750 /* default implementation */
751 iro = get_irn_opcode(n);
763 mode = get_irn_mode(n);
765 if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
766 (mode != mode_T || iro == iro_Proj))
767 fprintf(F, "%s", get_mode_name_ex(mode, NULL));
772 * Dump the type of a node n to a file F if it's known.
774 static int dump_node_typeinfo(FILE *F, ir_node *n)
778 if (ir_get_dump_flags() & ir_dump_flag_analysed_types) {
779 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
780 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
781 ir_type *tp = get_irn_typeinfo_type(n);
782 if (tp != firm_none_type) {
783 ir_fprintf(F, "[%+F]", tp);
792 typedef struct pns_lookup {
793 long nr; /**< the proj number */
794 const char *name; /**< the name of the Proj */
797 typedef struct proj_lookup {
798 unsigned code; /**< the opcode of the Proj predecessor */
799 unsigned num_data; /**< number of data entries */
800 const pns_lookup_t *data; /**< the data */
803 /** the lookup table for Proj(Start) names */
804 static const pns_lookup_t start_lut[] = {
805 #define X(a) { pn_Start_##a, #a }
813 /** the lookup table for Proj(Cond) names */
814 static const pns_lookup_t cond_lut[] = {
815 #define X(a) { pn_Cond_##a, #a }
821 /** the lookup table for Proj(Call) names */
822 static const pns_lookup_t call_lut[] = {
823 #define X(a) { pn_Call_##a, #a }
831 /** the lookup table for Proj(Div) names */
832 static const pns_lookup_t div_lut[] = {
833 #define X(a) { pn_Div_##a, #a }
841 /** the lookup table for Proj(Mod) names */
842 static const pns_lookup_t mod_lut[] = {
843 #define X(a) { pn_Mod_##a, #a }
851 /** the lookup table for Proj(Load) names */
852 static const pns_lookup_t load_lut[] = {
853 #define X(a) { pn_Load_##a, #a }
861 /** the lookup table for Proj(Store) names */
862 static const pns_lookup_t store_lut[] = {
863 #define X(a) { pn_Store_##a, #a }
870 /** the lookup table for Proj(Alloc) names */
871 static const pns_lookup_t alloc_lut[] = {
872 #define X(a) { pn_Alloc_##a, #a }
880 /** the lookup table for Proj(CopyB) names */
881 static const pns_lookup_t copyb_lut[] = {
882 #define X(a) { pn_CopyB_##a, #a }
889 /** the lookup table for Proj(InstOf) names */
890 static const pns_lookup_t instof_lut[] = {
891 #define X(a) { pn_InstOf_##a, #a }
899 /** the lookup table for Proj(Raise) names */
900 static const pns_lookup_t raise_lut[] = {
901 #define X(a) { pn_Raise_##a, #a }
907 /** the lookup table for Proj(Bound) names */
908 static const pns_lookup_t bound_lut[] = {
909 #define X(a) { pn_Bound_##a, #a }
917 /** the Proj lookup table */
918 static const proj_lookup_t proj_lut[] = {
919 #define E(a) ARRAY_SIZE(a), a
920 { iro_Start, E(start_lut) },
921 { iro_Cond, E(cond_lut) },
922 { iro_Call, E(call_lut) },
923 { iro_Div, E(div_lut) },
924 { iro_Mod, E(mod_lut) },
925 { iro_Load, E(load_lut) },
926 { iro_Store, E(store_lut) },
927 { iro_Alloc, E(alloc_lut) },
928 { iro_CopyB, E(copyb_lut) },
929 { iro_InstOf, E(instof_lut) },
930 { iro_Raise, E(raise_lut) },
931 { iro_Bound, E(bound_lut) }
936 * Dump additional node attributes of some nodes to a file F.
938 static void dump_node_nodeattr(FILE *F, ir_node *n)
943 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
945 /* call the dump_node operation if available */
946 if (ops->dump_node) {
947 ops->dump_node(F, n, dump_node_nodeattr_txt);
951 switch (get_irn_opcode(n)) {
953 ir_fprintf(F, "%T ", get_Const_tarval(n));
957 pred = get_Proj_pred(n);
958 proj_nr = get_Proj_proj(n);
959 code = get_irn_opcode(pred);
961 if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
962 fprintf(F, "Arg %ld ", proj_nr);
963 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
964 fprintf(F, "%ld ", proj_nr);
966 unsigned i, j, f = 0;
968 for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
969 if (code == proj_lut[i].code) {
970 for (j = 0; j < proj_lut[i].num_data; ++j) {
971 if (proj_nr == proj_lut[i].data[j].nr) {
972 fprintf(F, "%s ", proj_lut[i].data[j].name);
981 fprintf(F, "%ld ", proj_nr);
982 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
983 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
985 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
991 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
994 ir_fprintf(F, "(%+F)", get_Cast_type(n));
997 fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
1000 fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
1003 ir_fprintf(F, "(%+F)", get_CopyB_type(n));
1011 static void dump_node_ana_vals(FILE *F, ir_node *n)
1018 void dump_node_label(FILE *F, ir_node *n)
1020 dump_node_opcode(F, n);
1022 dump_node_mode(F, n);
1024 dump_node_typeinfo(F, n);
1025 dump_node_nodeattr(F, n);
1026 if (flags & ir_dump_flag_number_label) {
1027 fprintf(F, "%ld", get_irn_node_nr(n));
1029 if (flags & ir_dump_flag_idx_label) {
1030 fprintf(F, ":%u", get_irn_idx(n));
1034 void dump_vrp_info(FILE *F, ir_node *n)
1036 vrp_attr *vrp = vrp_get_info(n);
1041 fprintf(F, "range_type: %d\n", (int) vrp->range_type);
1042 if (vrp->range_type == VRP_RANGE || vrp->range_type ==
1044 ir_fprintf(F, "range_bottom: %F\n",vrp->range_bottom);
1045 ir_fprintf(F, "range_top: %F\n", vrp->range_top);
1047 ir_fprintf(F, "bits_set: %T\n", vrp->bits_set);
1048 ir_fprintf(F, "bits_not_set: %T\n", vrp->bits_not_set);
1052 * Dumps the attributes of a node n into the file F.
1053 * Currently this is only the color of a node.
1055 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1061 print_vcg_color(F, ird_color_error);
1065 if (dump_node_vcgattr_hook != NULL) {
1066 dump_node_vcgattr_hook(F, node, local);
1070 n = local ? local : node;
1072 if (overrule_nodecolor != ird_color_default_node) {
1073 print_vcg_color(F, overrule_nodecolor);
1077 mode = get_irn_mode(n);
1078 if (mode == mode_M) {
1079 print_vcg_color(F, ird_color_memory);
1082 if (mode == mode_X) {
1083 print_vcg_color(F, ird_color_controlflow);
1087 switch (get_irn_opcode(n)) {
1090 print_vcg_color(F, ird_color_anchor);
1093 print_vcg_color(F, ird_color_error);
1096 print_vcg_color(F, ird_color_block_background);
1099 print_vcg_color(F, ird_color_phi);
1102 print_vcg_color(F, ird_color_memory);
1106 print_vcg_color(F, ird_color_const);
1109 print_vcg_color(F, ird_color_proj);
1112 ir_op *op = get_irn_op(node);
1114 if (is_op_constlike(op)) {
1115 print_vcg_color(F, ird_color_const);
1116 } else if (is_op_uses_memory(op)) {
1117 print_vcg_color(F, ird_color_uses_memory);
1118 } else if (is_op_cfopcode(op) || is_op_forking(op)) {
1119 print_vcg_color(F, ird_color_controlflow);
1125 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1127 hook_entry_t *info = XMALLOC(hook_entry_t);
1129 info->hook._hook_node_info = cb;
1130 info->context = data;
1131 register_hook(hook_node_info, info);
1136 void dump_remove_node_info_callback(void *handle)
1138 hook_entry_t *info = (hook_entry_t*)handle;
1139 unregister_hook(hook_node_info, info);
1144 * Dump the node information of a node n to a file F.
1146 static void dump_node_info(FILE *F, ir_node *n)
1148 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1150 fprintf(F, " info1: \"");
1151 dump_irnode_to_file(F, n);
1152 /* call the dump_node operation if available */
1154 ops->dump_node(F, n, dump_node_info_txt);
1156 /* allow additional info to be added */
1157 hook_node_info(F, n);
1161 static int is_constlike_node(const ir_node *node)
1163 const ir_op *op = get_irn_op(node);
1164 return is_op_constlike(op);
1168 /** outputs the predecessors of n, that are constants, local. I.e.,
1169 generates a copy of the constant predecessors for each node called with. */
1170 static void dump_const_node_local(FILE *F, ir_node *n)
1173 if (!get_opt_dump_const_local()) return;
1175 /* Use visited flag to avoid outputting nodes twice.
1176 initialize it first. */
1177 for (i = 0; i < get_irn_arity(n); i++) {
1178 ir_node *con = get_irn_n(n, i);
1179 if (is_constlike_node(con)) {
1180 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1184 for (i = 0; i < get_irn_arity(n); i++) {
1185 ir_node *con = get_irn_n(n, i);
1186 if (is_constlike_node(con) && !irn_visited_else_mark(con)) {
1187 /* Generate a new name for the node by appending the names of
1189 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1190 fprintf(F, " label: \"");
1191 dump_node_label(F, con);
1193 dump_node_info(F, con);
1194 dump_node_vcgattr(F, n, con, 0);
1200 /** If the block of an edge is a const_like node, dump it local with an edge */
1201 static void dump_const_block_local(FILE *F, ir_node *n)
1205 if (!get_opt_dump_const_local()) return;
1207 blk = get_nodes_block(n);
1208 if (is_constlike_node(blk)) {
1209 /* Generate a new name for the node by appending the names of
1211 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1212 fprintf(F, "\" label: \"");
1213 dump_node_label(F, blk);
1215 dump_node_info(F, blk);
1216 dump_node_vcgattr(F, n, blk, 0);
1219 fprintf(F, "edge: { sourcename: \"");
1221 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1223 if (dump_edge_vcgattr_hook) {
1225 if (dump_edge_vcgattr_hook(F, n, -1)) {
1229 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1234 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1239 * prints the error message of a node to a file F as info2.
1241 static void print_node_error(FILE *F, const char *err_msg)
1246 fprintf(F, " info2: \"%s\"", err_msg);
1250 * prints debug messages of a node to file F as info3.
1252 static void print_dbg_info(FILE *F, dbg_info *dbg)
1256 ir_dbg_info_snprint(buf, sizeof(buf), dbg);
1258 fprintf(F, " info3: \"%s\"\n", buf);
1262 static void print_type_dbg_info(FILE *F, type_dbg_info *dbg)
1272 static void dump_node(FILE *F, ir_node *n)
1277 if (get_opt_dump_const_local() && is_constlike_node(n))
1280 /* dump this node */
1281 fputs("node: {title: \"", F);
1285 fputs(" label: \"", F);
1286 bad = ! irn_verify_irg_dump(n, current_ir_graph, &p);
1287 dump_node_label(F, n);
1288 dump_node_ana_vals(F, n);
1289 //dump_node_ana_info(F, n);
1292 if (get_op_flags(get_irn_op(n)) & irop_flag_dump_noinput) {
1293 //fputs(" node_class:23", F);
1296 dump_node_info(F, n);
1297 print_node_error(F, p);
1298 print_dbg_info(F, get_irn_dbg_info(n));
1299 dump_node_vcgattr(F, n, NULL, bad);
1301 dump_const_node_local(F, n);
1303 if (dump_node_edge_hook)
1304 dump_node_edge_hook(F, n);
1307 /** dump the edge to the block this node belongs to */
1308 static void dump_ir_block_edge(FILE *F, ir_node *n)
1310 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1312 ir_node *block = get_nodes_block(n);
1314 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1315 dump_const_block_local(F, n);
1317 fprintf(F, "edge: { sourcename: \"");
1319 fprintf(F, "\" targetname: ");
1320 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1322 if (dump_edge_vcgattr_hook) {
1324 if (dump_edge_vcgattr_hook(F, n, -1)) {
1328 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1333 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1338 static void print_data_edge_vcgattr(FILE *F, ir_node *from, int to)
1341 * do not use get_nodes_block() here, will fail
1342 * if the irg is not pinned.
1344 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1345 fprintf(F, INTRA_DATA_EDGE_ATTR);
1347 fprintf(F, INTER_DATA_EDGE_ATTR);
1350 static void print_mem_edge_vcgattr(FILE *F, ir_node *from, int to)
1353 * do not use get_nodes_block() here, will fail
1354 * if the irg is not pinned.
1356 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1357 fprintf(F, INTRA_MEM_EDGE_ATTR);
1359 fprintf(F, INTER_MEM_EDGE_ATTR);
1362 /** Print the vcg attributes for the edge from node "from" to its "to"th input */
1363 static void print_edge_vcgattr(FILE *F, ir_node *from, int to)
1367 if (dump_edge_vcgattr_hook)
1368 if (dump_edge_vcgattr_hook(F, from, to))
1371 if ((flags & ir_dump_flag_back_edges) && is_backedge(from, to))
1372 fprintf(F, BACK_EDGE_ATTR);
1374 switch (get_irn_opcode(from)) {
1376 fprintf(F, CF_EDGE_ATTR);
1378 case iro_Start: break;
1381 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1382 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1384 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1388 if (is_Proj(from)) {
1389 if (get_irn_mode(from) == mode_M)
1390 print_mem_edge_vcgattr(F, from, to);
1391 else if (get_irn_mode(from) == mode_X)
1392 fprintf(F, CF_EDGE_ATTR);
1394 print_data_edge_vcgattr(F, from, to);
1396 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1397 print_mem_edge_vcgattr(F, from, to);
1398 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1399 fprintf(F, CF_EDGE_ATTR);
1401 print_data_edge_vcgattr(F, from, to);
1405 /** dump edges to our inputs */
1406 static void dump_ir_data_edges(FILE *F, ir_node *n)
1410 if (!(flags & ir_dump_flag_keepalive_edges) && is_End(n)) {
1411 /* the End node has only keep-alive edges */
1415 /* dump the dependency edges. */
1416 num = get_irn_deps(n);
1417 for (i = 0; i < num; ++i) {
1418 ir_node *dep = get_irn_dep(n, i);
1421 print_node_edge_kind(F, n);
1422 fprintf(F, "{sourcename: \"");
1424 fprintf(F, "\" targetname: ");
1425 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1426 PRINT_CONSTID(n, dep);
1432 fprintf(F, " label: \"%d\" ", i);
1433 fprintf(F, " color: darkgreen}\n");
1437 num = get_irn_arity(n);
1438 for (i = 0; i < num; i++) {
1439 ir_node *pred = get_irn_n(n, i);
1442 if ((flags & ir_dump_flag_back_edges) && is_backedge(n, i)) {
1443 fprintf(F, "backedge: {sourcename: \"");
1445 print_node_edge_kind(F, n);
1446 fprintf(F, "{sourcename: \"");
1449 fprintf(F, "\" targetname: ");
1450 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1451 PRINT_CONSTID(n, pred);
1453 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1455 fprintf(F, " label: \"%d\" ", i);
1456 print_edge_vcgattr(F, n, i);
1464 static void dump_ir_edges(ir_node *node, void *env)
1467 FILE *F = (FILE*)env;
1468 const ir_edge_t *edge;
1470 foreach_out_edge(node, edge) {
1471 ir_node *succ = get_edge_src_irn(edge);
1473 print_node_edge_kind(F, succ);
1474 fprintf(F, "{sourcename: \"");
1476 fprintf(F, "\" targetname: \"");
1480 fprintf(F, " label: \"%d\" ", i);
1481 fprintf(F, OUT_EDGE_ATTR);
1488 /** Dumps a node and its edges but not the block edge */
1489 static void dump_node_wo_blockedge(ir_node *n, void *env)
1491 FILE *F = (FILE*)env;
1493 dump_ir_data_edges(F, n);
1496 /** Dumps a node and its edges. */
1497 static void dump_node_with_edges(ir_node *n, void *env)
1499 FILE *F = (FILE*)env;
1500 dump_node_wo_blockedge(n, env);
1501 if (!node_floats(n))
1502 dump_ir_block_edge(F, n);
1505 /** Dumps a const-like node. */
1506 static void dump_const_node(ir_node *n, void *env)
1508 if (is_Block(n)) return;
1509 dump_node_wo_blockedge(n, env);
1512 /***********************************************************************/
1513 /* the following routines dump the nodes/irgs bracketed to graphs. */
1514 /***********************************************************************/
1516 /** Dumps a constant expression as entity initializer, array bound ... */
1517 static void dump_const_expression(FILE *F, ir_node *value)
1519 ir_graph *rem = current_ir_graph;
1520 ir_dump_flags_t old_flags = ir_get_dump_flags();
1521 ir_remove_dump_flags(ir_dump_flag_consts_local);
1523 current_ir_graph = get_const_code_irg();
1524 irg_walk(value, dump_const_node, NULL, F);
1525 /* Decrease visited flag so that we walk with the same flag for the next
1526 expression. This guarantees that we don't dump the same node twice,
1527 as for const expressions cse is performed to save memory. */
1528 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1530 ir_set_dump_flags(old_flags);
1531 current_ir_graph = rem;
1534 /** Dump a block as graph containing its nodes.
1536 * Expects to find nodes belonging to the block as list in its
1538 * Dumps the edges of all nodes including itself. */
1539 static void dump_whole_block(FILE *F, ir_node *block)
1542 ird_color_t color = ird_color_block_background;
1544 assert(is_Block(block));
1546 fprintf(F, "graph: { title: \"");
1547 PRINT_NODEID(block);
1548 fprintf(F, "\" label: \"");
1549 dump_node_label(F, block);
1551 /* colorize blocks */
1552 if (! get_Block_matured(block))
1553 color = ird_color_block_background;
1555 fprintf(F, "\" status:clustered ");
1556 print_vcg_color(F, color);
1559 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1560 dump_node_info(F, block);
1561 print_dbg_info(F, get_irn_dbg_info(block));
1563 /* dump the blocks edges */
1564 dump_ir_data_edges(F, block);
1566 if (dump_block_edge_hook)
1567 dump_block_edge_hook(F, block);
1569 /* dump the nodes that go into the block */
1570 for (node = (ir_node*)ird_get_irn_link(block); node; node = (ir_node*)ird_get_irn_link(node)) {
1572 dump_ir_data_edges(F, node);
1575 /* Close the vcg information for the block */
1577 dump_const_node_local(F, block);
1581 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1582 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1583 static void dump_block_graph(FILE *F, ir_graph *irg)
1586 ir_graph *rem = current_ir_graph;
1587 ir_node **arr = (ir_node**)ird_get_irg_link(irg);
1588 current_ir_graph = irg;
1590 for (i = 0, n = ARR_LEN(arr); i < n; ++i) {
1591 ir_node *node = arr[i];
1592 if (is_Block(node)) {
1593 /* Dumps the block and all the nodes in the block, which are to
1594 be found in Block->link. */
1595 dump_whole_block(F, node);
1597 /* Nodes that are not in a Block. */
1599 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1600 dump_const_block_local(F, node);
1602 dump_ir_data_edges(F, node);
1604 if ((flags & ir_dump_flag_iredges) && edges_activated(irg))
1605 dump_ir_edges(node, F);
1608 if ((flags & ir_dump_flag_loops)
1609 && is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1610 dump_loop_nodes_into_graph(F, irg);
1612 current_ir_graph = rem;
1616 * Dump the info for an irg.
1617 * Parsed by XVCG but not shown. use yComp.
1619 static void dump_graph_info(FILE *F, ir_graph *irg)
1621 fprintf(F, "info1: \"");
1622 dump_entity_to_file(F, get_irg_entity(irg));
1625 /* dump graph state */
1626 fprintf(F, "state:");
1627 if (is_irg_state(irg, IR_GRAPH_STATE_ARCH_DEP))
1628 fprintf(F, " arch_dep");
1629 if (is_irg_state(irg, IR_GRAPH_STATE_MODEB_LOWERED))
1630 fprintf(F, " modeb_lowered");
1631 if (is_irg_state(irg, IR_GRAPH_STATE_NORMALISATION2))
1632 fprintf(F, " normalisation2");
1633 if (is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING))
1634 fprintf(F, " implicit_bitfield_masking");
1635 if (is_irg_state(irg, IR_GRAPH_STATE_OPTIMIZE_UNREACHABLE_CODE))
1636 fprintf(F, " optimize_unreachable_code");
1637 if (is_irg_state(irg, IR_GRAPH_STATE_NO_CRITICAL_EDGES))
1638 fprintf(F, " no_critical_edges");
1639 if (is_irg_state(irg, IR_GRAPH_STATE_NO_BADS))
1640 fprintf(F, " no_bads");
1641 if (is_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE))
1642 fprintf(F, " no_unreachable_code");
1643 if (is_irg_state(irg, IR_GRAPH_STATE_ONE_RETURN))
1644 fprintf(F, " one_return");
1645 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE))
1646 fprintf(F, " consistent_dominance");
1647 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE))
1648 fprintf(F, " consistent_postdominance");
1649 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUT_EDGES))
1650 fprintf(F, " consistent_out_edges");
1651 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))
1652 fprintf(F, " consistent_outs");
1653 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO))
1654 fprintf(F, " consistent_loopinfo");
1655 if (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE))
1656 fprintf(F, " consistent_entity_usage");
1657 if (is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
1658 fprintf(F, " valid_exended_blocks");
1662 /** Dumps an irg as a graph clustered by block nodes.
1663 * If interprocedural view edges can point to nodes out of this graph.
1665 static void dump_graph_from_list(FILE *F, ir_graph *irg)
1667 ir_entity *ent = get_irg_entity(irg);
1669 fprintf(F, "graph: { title: \"");
1671 fprintf(F, "\" label: \"%s\" status:clustered color:%s \n",
1672 get_ent_dump_name(ent), color_names[ird_color_prog_background]);
1674 dump_graph_info(F, irg);
1675 print_dbg_info(F, get_entity_dbg_info(ent));
1677 dump_block_graph(F, irg);
1679 /* Close the vcg information for the irg */
1680 fprintf(F, "}\n\n");
1683 /*******************************************************************/
1684 /* Basic type and entity nodes and edges. */
1685 /*******************************************************************/
1687 /** dumps the edges between nodes and their type or entity attributes. */
1688 static void dump_node2type_edges(ir_node *n, void *env)
1690 FILE *F = (FILE*)env;
1693 switch (get_irn_opcode(n)) {
1695 /* @@@ some consts have an entity */
1698 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1699 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1702 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1705 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1708 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1711 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1714 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1722 static int print_type_info(FILE *F, ir_type *tp)
1726 if (get_type_state(tp) == layout_undefined) {
1727 fprintf(F, "state: layout_undefined\n");
1729 fprintf(F, "state: layout_fixed,\n");
1731 if (get_type_mode(tp))
1732 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1733 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1738 static void print_typespecific_info(FILE *F, ir_type *tp)
1740 switch (get_type_tpop_code(tp)) {
1742 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1747 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1748 fprintf(F, "params: %d\n", get_method_n_params(tp));
1749 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1755 case tpo_enumeration:
1767 static void print_typespecific_vcgattr(FILE *F, ir_type *tp)
1769 switch (get_type_tpop_code(tp)) {
1771 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1774 fprintf(F, " " TYPE_METH_NODE_ATTR);
1782 case tpo_enumeration:
1793 void dump_type_node(FILE *F, ir_type *tp)
1795 fprintf(F, "node: {title: ");
1797 fprintf(F, " label: \"");
1798 if (tp->dbi != NULL) {
1800 ir_print_type(buf, sizeof(buf), tp);
1801 fprintf(F, "%s '%s'", get_type_tpop_name(tp), buf);
1803 ir_fprintf(F, "%+F", tp);
1805 fputs("\" info1: \"", F);
1806 dump_type_to_file(F, tp);
1808 print_type_dbg_info(F, get_type_dbg_info(tp));
1809 print_typespecific_vcgattr(F, tp);
1813 static void dump_entity_node(FILE *F, ir_entity *ent)
1815 fprintf(F, "node: {title: \"");
1816 PRINT_ENTID(ent); fprintf(F, "\"");
1817 fprintf(F, " label: ");
1818 fprintf(F, "\"%s\" ", get_ent_dump_name(ent));
1820 print_vcg_color(F, ird_color_entity);
1821 fprintf(F, "\n info1: \"");
1823 dump_entity_to_file(F, ent);
1826 print_dbg_info(F, get_entity_dbg_info(ent));
1830 static void dump_enum_item(FILE *F, ir_type *tp, size_t pos)
1833 ir_enum_const *ec = get_enumeration_const(tp, pos);
1834 ident *id = get_enumeration_const_nameid(ec);
1835 ir_tarval *tv = get_enumeration_value(ec);
1838 tarval_snprintf(buf, sizeof(buf), tv);
1840 strncpy(buf, "<not set>", sizeof(buf));
1841 fprintf(F, "node: {title: \"");
1842 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1843 fprintf(F, " label: ");
1844 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1845 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1849 * Dumps a new style initializer.
1851 static void dump_entity_initializer(FILE *F, const ir_entity *ent)
1859 * type-walker: Dumps a type or entity and its edges.
1861 static void dump_type_info(type_or_ent tore, void *env)
1863 FILE *F = (FILE*)env;
1864 size_t i = 0; /* to shutup gcc */
1866 /* dump this type or entity */
1868 switch (get_kind(tore.ent)) {
1870 ir_entity *ent = tore.ent;
1873 dump_entity_node(F, ent);
1875 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1876 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1877 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1878 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1879 if (is_Class_type(get_entity_owner(ent))) {
1880 for (i = get_entity_n_overwrites(ent); i > 0;)
1881 print_ent_ent_edge(F, ent, get_entity_overwrites(ent, --i), 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
1883 /* attached subgraphs */
1884 if (! (flags & ir_dump_flag_no_entity_values)) {
1885 if (ent->initializer != NULL) {
1886 /* new style initializers */
1887 dump_entity_initializer(F, ent);
1888 } else if (entity_has_compound_ent_values(ent)) {
1889 /* old style compound entity values */
1890 for (i = get_compound_ent_n_values(ent); i > 0;) {
1891 value = get_compound_ent_value(ent, --i);
1893 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1894 dump_const_expression(F, value);
1895 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ird_color_none, ENT_CORR_EDGE_ATTR, i);
1897 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1898 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1899 get_compound_ent_value_member(ent, i), i);
1908 ir_type *tp = tore.typ;
1909 dump_type_node(F, tp);
1910 /* and now the edges */
1911 switch (get_type_tpop_code(tp)) {
1913 for (i = get_class_n_supertypes(tp); i > 0;) {
1915 print_type_type_edge(F, tp, get_class_supertype(tp, i), TYPE_SUPER_EDGE_ATTR);
1917 for (i = get_class_n_members(tp); i > 0;) {
1919 print_type_ent_edge(F, tp, get_class_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1923 for (i = get_struct_n_members(tp); i > 0;) {
1925 print_type_ent_edge(F, tp, get_struct_member(tp, i), TYPE_MEMBER_EDGE_ATTR);
1929 for (i = get_method_n_params(tp); i > 0;) {
1931 print_type_type_edge(F, tp, get_method_param_type(tp, i), METH_PAR_EDGE_ATTR,i);
1933 for (i = get_method_n_ress(tp); i > 0;) {
1935 print_type_type_edge(F, tp, get_method_res_type(tp, i), METH_RES_EDGE_ATTR,i);
1939 for (i = get_union_n_members(tp); i > 0;) {
1941 print_type_ent_edge(F, tp, get_union_member(tp, i), UNION_EDGE_ATTR);
1945 print_type_type_edge(F, tp, get_array_element_type(tp), ARR_ELT_TYPE_EDGE_ATTR);
1946 print_type_ent_edge(F, tp, get_array_element_entity(tp), ARR_ENT_EDGE_ATTR);
1947 for (i = get_array_n_dimensions(tp); i > 0;) {
1948 ir_node *upper, *lower;
1951 upper = get_array_upper_bound(tp, i);
1952 lower = get_array_lower_bound(tp, i);
1953 print_node_type_edge(F, upper, tp, "label: \"upper %zu\"", get_array_order(tp, i));
1954 print_node_type_edge(F, lower, tp, "label: \"lower %zu\"", get_array_order(tp, i));
1955 dump_const_expression(F, upper);
1956 dump_const_expression(F, lower);
1959 case tpo_enumeration:
1960 for (i = get_enumeration_n_enums(tp); i > 0;) {
1962 dump_enum_item(F, tp, i);
1963 print_enum_item_edge(F, tp, i, "label: \"item %zu\"", i);
1967 print_type_type_edge(F, tp, get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1974 break; /* case k_type */
1977 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1978 } /* switch kind_or_entity */
1981 /** For dumping class hierarchies.
1982 * Dumps a class type node and a superclass edge.
1984 static void dump_class_hierarchy_node(type_or_ent tore, void *ctx)
1986 FILE *F = (FILE*)ctx;
1987 size_t i = 0; /* to shutup gcc */
1989 /* dump this type or entity */
1990 switch (get_kind(tore.ent)) {
1992 ir_entity *ent = tore.ent;
1993 if (get_entity_owner(ent) == get_glob_type()) break;
1994 if (!is_Method_type(get_entity_type(ent)))
1996 if (flags & ir_dump_flag_entities_in_hierarchy
1997 && is_Class_type(get_entity_owner(ent))) {
1999 dump_entity_node(F, ent);
2001 print_type_ent_edge(F, get_entity_owner(ent), ent, TYPE_MEMBER_EDGE_ATTR);
2002 for (i = get_entity_n_overwrites(ent); i > 0;) {
2004 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ird_color_none, ENT_OVERWRITES_EDGE_ATTR);
2010 ir_type *tp = tore.typ;
2011 if (tp == get_glob_type())
2013 switch (get_type_tpop_code(tp)) {
2015 dump_type_node(F, tp);
2016 /* and now the edges */
2017 for (i = get_class_n_supertypes(tp); i > 0;) {
2019 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2024 break; /* case k_type */
2027 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2028 } /* switch kind_or_entity */
2031 /*******************************************************************/
2032 /* dump analysis information that is expressed in graph terms. */
2033 /*******************************************************************/
2035 /* dump out edges */
2036 static void dump_out_edge(ir_node *n, void *env)
2038 FILE *F = (FILE*)env;
2040 for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
2041 ir_node *succ = get_irn_out(n, i);
2043 print_node_edge_kind(F, succ);
2044 fprintf(F, "{sourcename: \"");
2046 fprintf(F, "\" targetname: \"");
2048 fprintf(F, "\" color: red linestyle: dashed");
2053 static void dump_loop_label(FILE *F, ir_loop *loop)
2055 fprintf(F, "loop %u, %lu sons, %lu nodes",
2056 get_loop_depth(loop), (unsigned long) get_loop_n_sons(loop),
2057 (unsigned long) get_loop_n_nodes(loop));
2060 static void dump_loop_info(FILE *F, ir_loop *loop)
2062 fprintf(F, " info1: \"");
2063 fprintf(F, " loop nr: %ld", get_loop_loop_nr(loop));
2064 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
2065 fprintf(F, "\n The loop was analyzed %ld times.", (long int) PTR_TO_INT(get_loop_link(loop)));
2070 static void dump_loop_node(FILE *F, ir_loop *loop)
2072 fprintf(F, "node: {title: \"");
2074 fprintf(F, "\" label: \"");
2075 dump_loop_label(F, loop);
2077 dump_loop_info(F, loop);
2081 static void dump_loop_node_edge(FILE *F, ir_loop *loop, size_t i)
2084 fprintf(F, "edge: {sourcename: \"");
2086 fprintf(F, "\" targetname: \"");
2087 PRINT_NODEID(get_loop_node(loop, i));
2088 fprintf(F, "\" color: green");
2092 static void dump_loop_son_edge(FILE *F, ir_loop *loop, size_t i)
2095 fprintf(F, "edge: {sourcename: \"");
2097 fprintf(F, "\" targetname: \"");
2098 PRINT_LOOPID(get_loop_son(loop, i));
2099 ir_fprintf(F, "\" color: darkgreen label: \"%zu\"}\n",
2100 get_loop_element_pos(loop, get_loop_son(loop, i)));
2103 static void dump_loops(FILE *F, ir_loop *loop)
2106 /* dump this loop node */
2107 dump_loop_node(F, loop);
2109 /* dump edges to nodes in loop -- only if it is a real loop */
2110 if (get_loop_depth(loop) != 0) {
2111 for (i = get_loop_n_nodes(loop); i > 0;) {
2113 dump_loop_node_edge(F, loop, i);
2116 for (i = get_loop_n_sons(loop); i > 0;) {
2118 dump_loops(F, get_loop_son(loop, i));
2119 dump_loop_son_edge(F, loop, i);
2123 static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg)
2125 ir_loop *loop = get_irg_loop(irg);
2128 ir_graph *rem = current_ir_graph;
2129 current_ir_graph = irg;
2131 dump_loops(F, loop);
2133 current_ir_graph = rem;
2139 * dumps the VCG header
2141 void dump_vcg_header(FILE *F, const char *name, const char *layout, const char *orientation)
2145 = (flags & ir_dump_flag_disable_edge_labels) ? "no" : "yes";
2149 if (! layout) layout = "Compilergraph";
2150 if (!orientation) orientation = "bottom_to_top";
2154 "graph: { title: \"ir graph of %s\"\n"
2155 "display_edge_labels: %s\n"
2156 "layoutalgorithm: mindepth //$ \"%s\"\n"
2157 "manhattan_edges: yes\n"
2158 "port_sharing: no\n"
2160 "classname 1: \"intrablock Data\"\n"
2161 "classname 2: \"Block\"\n"
2162 "classname 3: \"Entity type\"\n"
2163 "classname 4: \"Entity owner\"\n"
2164 "classname 5: \"Method Param\"\n"
2165 "classname 6: \"Method Res\"\n"
2166 "classname 7: \"Super\"\n"
2167 "classname 8: \"Union\"\n"
2168 "classname 9: \"Points-to\"\n"
2169 "classname 10: \"Array Element Type\"\n"
2170 "classname 11: \"Overwrites\"\n"
2171 "classname 12: \"Member\"\n"
2172 "classname 13: \"Control Flow\"\n"
2173 "classname 14: \"intrablock Memory\"\n"
2174 "classname 15: \"Dominators\"\n"
2175 "classname 16: \"interblock Data\"\n"
2176 "classname 17: \"interblock Memory\"\n"
2177 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2178 "classname 19: \"Postdominators\"\n"
2179 "classname 20: \"Keep Alive\"\n"
2180 "classname 21: \"Out Edges\"\n"
2181 "classname 22: \"Macro Block Edges\"\n"
2182 //"classname 23: \"NoInput Nodes\"\n"
2183 "infoname 1: \"Attribute\"\n"
2184 "infoname 2: \"Verification errors\"\n"
2185 "infoname 3: \"Debug info\"\n",
2186 name, label, layout, orientation);
2188 for (i = 0; i < ird_color_count; ++i) {
2189 if (color_rgb[i] != NULL) {
2190 fprintf(F, "colorentry %s: %s\n", color_names[i], color_rgb[i]);
2197 * Dumps the vcg file footer
2199 void dump_vcg_footer(FILE *F)
2206 static void dump_blocks_as_subgraphs(FILE *out, ir_graph *irg)
2210 construct_block_lists(irg);
2213 * If we are in the interprocedural view, we dump not
2214 * only the requested irg but also all irgs that can be reached
2217 for (i = get_irp_n_irgs(); i > 0;) {
2218 ir_graph *other_irg = get_irp_irg(--i);
2219 ir_node **arr = (ir_node**)ird_get_irg_link(other_irg);
2223 dump_graph_from_list(out, other_irg);
2228 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
2229 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
2230 static void dump_extblock_graph(FILE *F, ir_graph *irg)
2233 ir_graph *rem = current_ir_graph;
2234 ir_extblk **arr = (ir_extblk**)ird_get_irg_link(irg);
2235 current_ir_graph = irg;
2237 for (i = 0, arr_len = ARR_LEN(arr); i < arr_len; ++i) {
2238 ir_extblk *extbb = arr[i];
2239 ir_node *leader = get_extbb_leader(extbb);
2242 fprintf(F, "graph: { title: \"");
2243 PRINT_EXTBBID(leader);
2244 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
2245 get_irn_node_nr(leader));
2247 for (j = 0, n_blks = ARR_LEN(extbb->blks); j < n_blks; ++j) {
2248 ir_node *node = extbb->blks[j];
2249 if (is_Block(node)) {
2250 /* Dumps the block and all the nodes in the block, which are to
2251 be found in Block->link. */
2252 dump_whole_block(F, node);
2254 /* Nodes that are not in a Block. */
2256 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
2257 dump_const_block_local(F, node);
2259 dump_ir_data_edges(F, node);
2265 if ((flags & ir_dump_flag_loops)
2266 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO)))
2267 dump_loop_nodes_into_graph(F, irg);
2269 current_ir_graph = rem;
2273 static void dump_blocks_extbb_grouped(FILE *F, ir_graph *irg)
2276 ir_entity *ent = get_irg_entity(irg);
2278 if (!is_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS))
2281 construct_extblock_lists(irg);
2283 fprintf(F, "graph: { title: \"");
2285 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2286 get_ent_dump_name(ent));
2288 dump_graph_info(F, irg);
2289 print_dbg_info(F, get_entity_dbg_info(ent));
2291 for (i = get_irp_n_irgs(); i > 0;) {
2292 ir_graph *other_irg = get_irp_irg(--i);
2293 list_tuple *lists = (list_tuple*)ird_get_irg_link(other_irg);
2296 /* dump the extended blocks first */
2297 if (ARR_LEN(lists->extbb_list)) {
2298 ird_set_irg_link(other_irg, lists->extbb_list);
2299 dump_extblock_graph(F, other_irg);
2302 /* we may have blocks without extended blocks, bad for instance */
2303 if (ARR_LEN(lists->blk_list)) {
2304 ird_set_irg_link(other_irg, lists->blk_list);
2305 dump_block_graph(F, other_irg);
2308 DEL_ARR_F(lists->extbb_list);
2309 DEL_ARR_F(lists->blk_list);
2314 /* Close the vcg information for the irg */
2315 fprintf(F, "}\n\n");
2320 void dump_ir_graph_file(FILE *out, ir_graph *irg)
2322 dump_vcg_header(out, get_irg_dump_name(irg), NULL, NULL);
2325 if (flags & ir_dump_flag_blocks_as_subgraphs) {
2326 if (flags & ir_dump_flag_group_extbb) {
2327 dump_blocks_extbb_grouped(out, irg);
2329 dump_blocks_as_subgraphs(out, irg);
2332 /* dump_node_with_edges must be called in post visiting predecessors */
2333 ird_walk_graph(irg, NULL, dump_node_with_edges, out);
2336 /* dump type info */
2337 if (flags & ir_dump_flag_with_typegraph) {
2338 ir_graph *rem = current_ir_graph;
2339 current_ir_graph = irg;
2341 type_walk_irg(irg, dump_type_info, NULL, out);
2342 inc_irg_visited(get_const_code_irg());
2343 /* dump edges from graph to type info */
2344 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, out);
2346 current_ir_graph = rem;
2349 /* dump iredges out edges */
2350 if ((flags & ir_dump_flag_iredges) && edges_activated(current_ir_graph)) {
2351 irg_walk_edges(get_irg_start_block(irg), dump_ir_edges, NULL, out);
2354 /* dump the out edges in a separate walk */
2355 if ((flags & ir_dump_flag_out_edges)
2356 && (is_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS))) {
2357 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, out);
2360 dump_vcg_footer(out);
2363 static void dump_block_to_cfg(ir_node *block, void *env)
2365 FILE *F = (FILE*)env;
2368 if (is_Bad(block) && get_irn_mode(block) == mode_X) {
2369 dump_node(F, block);
2372 if (is_Block(block)) {
2373 /* This is a block. Dump a node for the block. */
2374 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2375 fprintf(F, "\" label: \"");
2376 if (block == get_irg_start_block(get_irn_irg(block)))
2377 fprintf(F, "Start ");
2378 if (block == get_irg_end_block(get_irn_irg(block)))
2381 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2382 PRINT_NODEID(block);
2384 fprintf(F, "info1:\"");
2386 /* the generic version. */
2387 dump_irnode_to_file(F, block);
2389 fprintf(F, "\""); /* closing quote of info */
2391 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2392 (block == get_irg_end_block(get_irn_irg(block))) )
2393 fprintf(F, " color:blue ");
2397 /* Dump the edges */
2398 for (i = get_Block_n_cfgpreds(block) - 1; i >= 0; --i) {
2399 ir_node *pred = get_Block_cfgpred(block, i);
2401 pred = get_nodes_block(pred);
2402 fprintf(F, "edge: { sourcename: \"");
2403 PRINT_NODEID(block);
2404 fprintf(F, "\" targetname: \"");
2406 fprintf(F, "\"}\n");
2409 /* Dump dominator/postdominator edge */
2410 if (ir_get_dump_flags() & ir_dump_flag_dominance) {
2411 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_DOMINANCE) && get_Block_idom(block)) {
2412 ir_node *pred = get_Block_idom(block);
2413 fprintf(F, "edge: { sourcename: \"");
2414 PRINT_NODEID(block);
2415 fprintf(F, "\" targetname: \"");
2417 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2419 if (is_irg_state(get_irn_irg(block), IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE) && get_Block_ipostdom(block)) {
2420 ir_node *pred = get_Block_ipostdom(block);
2421 fprintf(F, "edge: { sourcename: \"");
2422 PRINT_NODEID(block);
2423 fprintf(F, "\" targetname: \"");
2425 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2431 void dump_cfg(FILE *F, ir_graph *irg)
2433 dump_vcg_header(F, get_irg_dump_name(irg), NULL, NULL);
2435 /* walk over the blocks in the graph */
2436 irg_walk_graph(irg, dump_block_to_cfg, NULL, F);
2441 void dump_callgraph(FILE *F)
2444 ir_dump_flags_t old_flags = ir_get_dump_flags();
2446 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2447 dump_vcg_header(F, "Callgraph", "Hierarchic", NULL);
2449 for (i = get_irp_n_irgs(); i > 0;) {
2450 ir_graph *irg = get_irp_irg(--i);
2451 ir_entity *ent = get_irg_entity(irg);
2452 size_t j, n_callees = get_irg_n_callees(irg);
2454 dump_entity_node(F, ent);
2455 for (j = 0; j < n_callees; ++j) {
2456 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2457 int be = is_irg_callee_backedge(irg, j);
2458 const char *attr = be
2459 ? "label:\"recursion %zu\""
2460 : "label:\"calls %zu\"";
2461 print_ent_ent_edge(F, ent, c, be, ird_color_entity, attr,
2462 get_irg_callee_loop_depth(irg, j));
2466 ir_set_dump_flags(old_flags);
2470 void dump_typegraph(FILE *out)
2472 dump_vcg_header(out, "All_types", "Hierarchic", NULL);
2473 type_walk(dump_type_info, NULL, out);
2474 dump_vcg_footer(out);
2477 void dump_class_hierarchy(FILE *out)
2479 dump_vcg_header(out, "class_hierarchy", "Hierarchic", NULL);
2480 type_walk(dump_class_hierarchy_node, NULL, out);
2481 dump_vcg_footer(out);
2484 static void dump_loops_standalone(FILE *F, ir_loop *loop)
2487 bool loop_node_started = false;
2489 size_t son_number = 0;
2491 ir_loop *son = NULL;
2493 /* Dump a new loop node. */
2494 dump_loop_node(F, loop);
2496 /* Dump the loop elements. */
2497 for (i = 0; i < get_loop_n_elements(loop); i++) {
2498 le = get_loop_element(loop, i);
2500 if (get_kind(son) == k_ir_loop) {
2502 /* We are a loop son -> Recurse */
2504 if (loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2505 fprintf(F, "\" }\n");
2506 fprintf(F, "edge: {sourcename: \"");
2508 fprintf(F, "\" targetname: \"");
2510 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2511 (unsigned long) first,
2512 (unsigned long) first,
2513 (unsigned long) i-1);
2514 loop_node_started = false;
2516 dump_loop_son_edge(F, loop, son_number++);
2517 dump_loops_standalone(F, son);
2518 } else if (get_kind(son) == k_ir_node) {
2519 /* We are a loop node -> Collect firm nodes */
2521 ir_node *n = le.node;
2522 if (!loop_node_started) {
2523 /* Start a new node which contains all firm nodes of the current loop */
2524 fprintf(F, "node: { title: \"");
2526 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2528 loop_node_started = true;
2533 dump_node_label(F, n);
2534 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2535 if (has_backedges(n)) fprintf(F, "\t loop head!");
2536 } else { /* for callgraph loop tree */
2538 assert(get_kind(son) == k_ir_graph);
2540 /* We are a loop node -> Collect firm graphs */
2542 if (!loop_node_started) {
2543 /* Start a new node which contains all firm nodes of the current loop */
2544 fprintf(F, "node: { title: \"");
2546 fprintf(F, "-%lu-nodes\" color: lightyellow label: \"",
2548 loop_node_started = true;
2552 fprintf(F, " %s", get_irg_dump_name(n));
2553 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2557 if (loop_node_started) {
2558 fprintf(F, "\" }\n");
2559 fprintf(F, "edge: {sourcename: \"");
2561 fprintf(F, "\" targetname: \"");
2563 fprintf(F, "-%lu-nodes\" label:\"%lu...%lu\"}\n",
2564 (unsigned long) first,
2565 (unsigned long) first,
2566 (unsigned long) i-1);
2567 loop_node_started = false;
2571 void dump_loop_tree(FILE *out, ir_graph *irg)
2573 ir_graph *rem = current_ir_graph;
2574 ir_dump_flags_t old_flags = ir_get_dump_flags();
2576 current_ir_graph = irg;
2577 ir_remove_dump_flags(ir_dump_flag_disable_edge_labels);
2579 dump_vcg_header(out, get_irg_dump_name(irg), "Tree", "top_to_bottom");
2581 if (get_irg_loop(irg))
2582 dump_loops_standalone(out, get_irg_loop(irg));
2584 dump_vcg_footer(out);
2586 ir_set_dump_flags(old_flags);
2587 current_ir_graph = rem;
2590 void dump_callgraph_loop_tree(FILE *out)
2592 dump_vcg_header(out, "callgraph looptree", "Tree", "top_to_bottom");
2593 dump_loops_standalone(out, irp->outermost_cg_loop);
2594 dump_vcg_footer(out);
2597 static void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes)
2601 int node_number = 0;
2603 if (flags & ir_dump_flag_loops)
2604 dump_loop_node(F, loop);
2606 for (i = 0; i < get_loop_n_elements(loop); i++) {
2607 loop_element le = get_loop_element(loop, i);
2608 if (*(le.kind) == k_ir_loop) {
2609 if (flags & ir_dump_flag_loops)
2610 dump_loop_son_edge(F, loop, son_number++);
2612 collect_nodeloop(F, le.son, loopnodes);
2614 if (flags & ir_dump_flag_loops)
2615 dump_loop_node_edge(F, loop, node_number++);
2616 eset_insert(loopnodes, le.node);
2621 static void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes,
2627 for (i = 0; i < get_loop_n_elements(loop); i++) {
2628 loop_element le = get_loop_element(loop, i);
2629 if (*(le.kind) == k_ir_loop) {
2631 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2633 if (is_Block(le.node)) start = 0; else start = -1;
2634 for (j = start; j < get_irn_arity(le.node); j++) {
2635 ir_node *pred = get_irn_n(le.node, j);
2636 if (!eset_contains(loopnodes, pred)) {
2637 eset_insert(extnodes, pred);
2638 if (!is_Block(pred)) {
2639 pred = get_nodes_block(pred);
2640 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2648 void dump_loop(FILE *F, ir_loop *l)
2650 eset *loopnodes = eset_create();
2651 eset *extnodes = eset_create();
2655 snprintf(name, sizeof(name), "loop_%ld", get_loop_loop_nr(l));
2656 dump_vcg_header(F, name, NULL, NULL);
2658 /* collect all nodes to dump */
2659 collect_nodeloop(F, l, loopnodes);
2660 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2662 /* build block lists */
2663 eset_foreach(loopnodes, ir_node*, n) {
2664 set_irn_link(n, NULL);
2666 eset_foreach(extnodes, ir_node*, n) {
2667 set_irn_link(n, NULL);
2669 eset_foreach(loopnodes, ir_node*, n) {
2671 b = get_nodes_block(n);
2672 set_irn_link(n, get_irn_link(b));
2676 eset_foreach(extnodes, ir_node*, n) {
2678 b = get_nodes_block(n);
2679 set_irn_link(n, get_irn_link(b));
2684 eset_foreach(loopnodes, ir_node*, b) {
2686 fprintf(F, "graph: { title: \"");
2688 fprintf(F, "\" label: \"");
2689 dump_node_opcode(F, b);
2690 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2691 fprintf(F, "\" status:clustered color:yellow\n");
2693 /* dump the blocks edges */
2694 dump_ir_data_edges(F, b);
2696 /* dump the nodes that go into the block */
2697 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2698 if (eset_contains(extnodes, n))
2699 overrule_nodecolor = ird_color_block_inout;
2701 overrule_nodecolor = ird_color_default_node;
2702 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2705 /* Close the vcg information for the block */
2707 dump_const_node_local(F, b);
2711 eset_foreach(extnodes, ir_node*, b) {
2713 fprintf(F, "graph: { title: \"");
2715 fprintf(F, "\" label: \"");
2716 dump_node_opcode(F, b);
2717 fprintf(F, " %ld:%u", get_irn_node_nr(b), get_irn_idx(b));
2718 fprintf(F, "\" status:clustered color:lightblue\n");
2720 /* dump the nodes that go into the block */
2721 for (n = (ir_node*)get_irn_link(b); n; n = (ir_node*)get_irn_link(n)) {
2722 if (!eset_contains(loopnodes, n))
2723 overrule_nodecolor = ird_color_block_inout;
2725 overrule_nodecolor = ird_color_default_node;
2726 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2729 /* Close the vcg information for the block */
2731 dump_const_node_local(F, b);
2735 eset_destroy(loopnodes);
2736 eset_destroy(extnodes);
2741 static bool obstack_init;
2742 static struct obstack obst;
2743 static char *dump_path;
2745 void ir_set_dump_path(const char *path)
2748 dump_path = xstrdup(path);
2751 static void add_string_escaped(const char *string)
2754 for (p = string; *p != '\0'; ++p) {
2757 obstack_1grow(&obst, '@');
2758 obstack_1grow(&obst, '1');
2759 } else if (c == '@') {
2760 obstack_1grow(&obst, '@');
2761 obstack_1grow(&obst, '2');
2763 obstack_1grow(&obst, c);
2768 static void add_dump_path(void)
2770 if (!obstack_init) {
2771 obstack_init(&obst);
2772 obstack_init = true;
2775 if (dump_path != NULL) {
2776 size_t len = strlen(dump_path);
2777 obstack_grow(&obst, dump_path, len);
2778 if (len > 0 && dump_path[len-1] != '/')
2779 obstack_1grow(&obst, '/');
2783 void dump_ir_graph_ext(ir_graph_dump_func func, ir_graph *graph,
2786 const char *dump_name = get_irg_dump_name(graph);
2790 if (!ir_should_dump(dump_name))
2795 add_string_escaped(dump_name);
2796 obstack_printf(&obst, "-%02u", graph->dump_nr++);
2798 if (suffix != NULL) {
2799 if (suffix[0] != '.')
2800 obstack_1grow(&obst, '-');
2801 add_string_escaped(suffix);
2803 obstack_1grow(&obst, '\0');
2805 file_name = (char*)obstack_finish(&obst);
2806 /* xvcg expects only <CR> so we need "b"inary mode (for win32) */
2807 out = fopen(file_name, "wb");
2808 obstack_free(&obst, file_name);
2811 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2819 void dump_ir_prog_ext(ir_prog_dump_func func, const char *suffix)
2826 obstack_printf(&obst, "%02u", irp->dump_nr++);
2827 if (suffix != NULL) {
2828 if (suffix[0] != '.')
2829 obstack_1grow(&obst, '-');
2830 add_string_escaped(suffix);
2832 obstack_1grow(&obst, '\0');
2834 file_name = (char*)obstack_finish(&obst);
2835 out = fopen(file_name, "wb");
2836 obstack_free(&obst, file_name);
2839 fprintf(stderr, "Couldn't open '%s': %s\n", file_name, strerror(errno));
2846 void dump_ir_graph(ir_graph *graph, const char *suffix)
2850 snprintf(buf, sizeof(buf), "%s.vcg", suffix);
2851 dump_ir_graph_ext(dump_ir_graph_file, graph, buf);
2854 void dump_all_ir_graphs(const char *suffix)
2856 size_t i, n_irgs = get_irp_n_irgs();
2858 for (i = 0; i < n_irgs; ++i) {
2859 ir_graph *irg = get_irp_irg(i);
2860 dump_ir_graph(irg, suffix);
2864 typedef struct pass_t {
2865 ir_prog_pass_t pass;
2870 * Wrapper around dump_all_ir_graphs().
2872 static int dump_all_ir_graphs_wrapper(ir_prog *irp, void *context)
2874 pass_t *pass = (pass_t*)context;
2877 dump_all_ir_graphs(pass->suffix);
2881 ir_prog_pass_t *dump_all_ir_graph_pass(const char *name, const char *suffix)
2883 size_t len = strlen(suffix) + 1;
2884 pass_t *pass = XMALLOCF(pass_t, suffix, len);
2885 ir_prog_pass_t *res = def_prog_pass_constructor(
2886 &pass->pass, name ? name : "dump_all_graphs", dump_all_ir_graphs_wrapper);
2888 /* this pass does not change anything, so neither dump nor verify is needed. */
2889 res->dump_irprog = ir_prog_no_dump;
2890 res->verify_irprog = ir_prog_no_verify;
2892 memcpy(pass->suffix, suffix, len);