2 * Copyright (C) 1995-2007 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 "firm_common_t.h"
56 #include "callgraph.h"
57 #include "irextbb_t.h"
59 #include "dbginfo_t.h"
71 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
72 extern void dump_irn_state(FILE *FL, ir_node *n);
73 extern int get_opt_dump_abstvals(void);
74 typedef unsigned long SeqNo;
75 extern SeqNo get_Block_seqno(ir_node *n);
78 /* basis for a color range for vcg */
79 static int n_colors = 0;
80 static int base_color = 0;
82 /** Dump only irgs with names that start with this string */
83 static ident *dump_file_filter_id = NULL;
85 #define ERROR_TXT "<ERROR>"
87 /*******************************************************************/
88 /* flags to steer output */
89 /*******************************************************************/
91 /** An option to turn off edge labels */
92 static int edge_label = 1;
93 /** An option to turn off dumping values of constant entities */
94 static int const_entities = 1;
95 /** An option to dump the keep alive edges */
96 static int dump_keepalive = 0;
97 /** An option to dump the new out edges */
98 static int dump_new_edges_flag = 0;
99 /** An option to dump ld_names instead of names. */
100 static int dump_ld_name = 1;
101 /** Compiler options to dump analysis information in dump_ir_graph */
102 static int dump_out_edge_flag = 0;
103 static int dump_loop_information_flag = 0;
104 static int dump_backedge_information_flag = 1;
105 static int dump_const_local = 0;
106 static int dump_node_idx_labels = 0;
107 /** An option to dump all graph anchors */
108 static int dump_anchors = 0;
110 int dump_dominator_information_flag = 0;
111 int opt_dump_analysed_type_info = 1;
112 int opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
114 static dumper_colors overrule_nodecolor = ird_color_default;
116 /** The vcg node attribute hook. */
117 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
118 /** The vcg node attribute hook. */
119 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
120 /** The vcg edge attribute hook. */
121 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
122 /** The vcg dump block edge hook */
123 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
124 /** The vcg dump node edge hook. */
125 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
127 /* Set the hook to be called to dump additional edges to a node. */
128 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func) {
129 dump_node_edge_hook = func;
132 /* Get the additional edge dump hook. */
133 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void) {
134 return dump_node_edge_hook;
137 /* Set the hook to be called to dump additional edges to a block. */
138 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func) {
139 dump_block_edge_hook = func;
142 /* Get the additional block edge dump hook. */
143 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void) {
144 return dump_node_edge_hook;
147 /* set the ir graph hook */
148 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
149 dump_ir_graph_hook = hook;
152 /* set the node attribute hook */
153 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
154 dump_node_vcgattr_hook = hook;
157 /* set the edge attribute hook */
158 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
159 dump_edge_vcgattr_hook = hook;
162 /* Returns 0 if dump_out_edge_flag or dump_loop_information_flag
163 * are set, else returns dump_const_local_flag.
165 int get_opt_dump_const_local(void) {
166 if (dump_out_edge_flag || dump_loop_information_flag || (dump_new_edges_flag && edges_activated(current_ir_graph)))
168 return dump_const_local;
171 /* Set a prefix filter for output functions. */
172 void only_dump_method_with_name(ident *name) {
173 dump_file_filter_id = name;
176 /* Returns the prefix filter set with only_dump_method_with_name(). */
177 ident *get_dump_file_filter_ident(void) {
178 return dump_file_filter_id;
181 /* Returns non-zero if dump file filter is not set, or if it is a prefix of name. */
182 int is_filtered_dump_name(ident *name) {
183 if (!dump_file_filter_id) return 1;
184 return id_is_prefix(dump_file_filter_id, name);
187 /* To turn off display of edge labels. Edge labels often cause xvcg to
188 abort with a segmentation fault. */
189 void turn_off_edge_labels(void) {
193 void dump_consts_local(int flag) {
194 dump_const_local = flag;
197 void dump_node_idx_label(int flag) {
198 dump_node_idx_labels = flag;
201 void dump_constant_entity_values(int flag) {
202 const_entities = flag;
205 void dump_keepalive_edges(int flag) {
206 dump_keepalive = flag;
209 void dump_new_edges(int flag) {
210 dump_new_edges_flag = flag;
213 int get_opt_dump_keepalive_edges(void) {
214 return dump_keepalive;
217 void dump_out_edges(int flag) {
218 dump_out_edge_flag = flag;
221 void dump_dominator_information(int flag) {
222 dump_dominator_information_flag = flag;
225 void dump_loop_information(int flag) {
226 dump_loop_information_flag = flag;
229 void dump_backedge_information(int flag) {
230 dump_backedge_information_flag = flag;
233 /* Dump the information of type field specified in ana/irtypeinfo.h.
234 * If the flag is set, the type name is output in [] in the node label,
235 * else it is output as info.
237 void set_opt_dump_analysed_type_info(int flag) {
238 opt_dump_analysed_type_info = flag;
241 void dump_pointer_values_to_info(int flag) {
242 opt_dump_pointer_values_to_info = flag;
245 void dump_ld_names(int flag) {
249 void dump_all_anchors(int flag) {
253 /* -------------- some extended helper functions ----------------- */
256 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
257 * in the later case, sets bad
259 const char *get_mode_name_ex(ir_mode *mode, int *bad) {
261 return get_mode_name(mode);
267 * returns the name of a type or <ERROR> if mode is NOT a mode object.
268 * in the later case, sets bad
270 const char *get_type_name_ex(ir_type *tp, int *bad) {
272 return get_type_name(tp);
278 * printf the VCG color to a file
280 static void print_vcg_color(FILE *F, dumper_colors color) {
281 static const char *color_names[32] = {
282 "white", "blue", "red", "green",
283 "yellow", "magenta", "cyan", "darkgray",
284 "darkblue", "darkred", "darkgreen", "darkyellow",
285 "darkmagenta", "darkcyan", "gold", "lightgray",
286 "lightblue", "lightred", "lightgreen", "lightyellow",
287 "lightmagenta", "lightcyan", "lilac", "turquoise",
288 "aquamarine", "khaki", "purple", "yellowgreen",
289 "pink", "orange", "orchid", "black"
292 if (color != ird_color_default)
293 fprintf(F, "color:%s", color_names[color]);
297 * prints the edge from a type S to a type T with additional info fmt, ...
300 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
305 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
306 fprintf(F, " targetname: "); PRINT_TYPEID(T);
307 vfprintf(F, fmt, ap);
313 * prints the edge from a type T to an entity E with additional info fmt, ...
316 static void print_type_ent_edge(FILE *F, ir_type *T, ir_entity *E, const char *fmt, ...)
321 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
322 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
323 vfprintf(F, fmt, ap);
329 * prints the edge from an entity E to an entity T with additional info fmt, ...
332 static void print_ent_ent_edge(FILE *F, ir_entity *E, ir_entity *T, int backedge, const char *fmt, ...)
338 fprintf(F, "backedge: { sourcename: \"");
340 fprintf(F, "edge: { sourcename: \"");
342 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
343 vfprintf(F, fmt, ap);
349 * prints the edge from an entity E to a type T with additional info fmt, ...
352 static void print_ent_type_edge(FILE *F, ir_entity *E, ir_type *T, const char *fmt, ...)
357 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
358 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
359 vfprintf(F, fmt, ap);
365 * prints the edge from a node N to a type T with additional info fmt, ...
368 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
373 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
374 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
375 vfprintf(F, fmt, ap);
381 * prints the edge from a node N to an entity E with additional info fmt, ...
384 static void print_node_ent_edge(FILE *F, const ir_node *N, ir_entity *E, const char *fmt, ...)
389 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
390 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
392 vfprintf(F, fmt, ap);
398 * prints the edge from an entity E to a node N with additional info fmt, ...
401 static void print_ent_node_edge(FILE *F, ir_entity *E, const ir_node *N, const char *fmt, ...)
406 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
407 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
408 vfprintf(F, fmt, ap);
414 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
417 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
422 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
423 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
424 vfprintf(F, fmt, ap);
429 /*-----------------------------------------------------------------*/
430 /* global and ahead declarations */
431 /*-----------------------------------------------------------------*/
433 static void dump_whole_node(ir_node *n, void *env);
434 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
436 /*-----------------------------------------------------------------*/
437 /* Helper functions. */
438 /*-----------------------------------------------------------------*/
441 * This map is used as a private link attr to be able to call dumper
442 * anywhere without destroying link fields.
444 static pmap *irdump_link_map = NULL;
446 /** NOT A STANDARD LIBFIRM INIT METHOD
448 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
449 * are off, we want to have as few interferences as possible. Therefore the
450 * initialization is performed lazily and not called from within init_firm.
452 * Creates the link attribute map. */
453 static void init_irdump(void) {
454 /* We need a new, empty map. */
455 if (irdump_link_map) pmap_destroy(irdump_link_map);
456 irdump_link_map = pmap_create();
457 if (!dump_file_filter_id)
458 dump_file_filter_id = new_id_from_str("");
462 * Returns the private link field.
464 static void *ird_get_irn_link(ir_node *n) {
466 if (!irdump_link_map) return NULL;
468 if (pmap_contains(irdump_link_map, (void *)n))
469 res = pmap_get(irdump_link_map, (void *)n);
474 * Sets the private link field.
476 static void ird_set_irn_link(ir_node *n, void *x) {
477 if (!irdump_link_map)
479 pmap_insert(irdump_link_map, (void *)n, x);
483 * Gets the private link field of an irg.
485 static void *ird_get_irg_link(ir_graph *irg) {
487 if (!irdump_link_map) return NULL;
489 if (pmap_contains(irdump_link_map, (void *)irg))
490 res = pmap_get(irdump_link_map, (void *)irg);
495 * Sets the private link field of an irg.
497 static void ird_set_irg_link(ir_graph *irg, void *x) {
498 if (!irdump_link_map) init_irdump();
499 pmap_insert(irdump_link_map, (void *)irg, x);
503 * Walker, clears the private link field.
505 static void clear_link(ir_node * node, void * env) {
507 ird_set_irn_link(node, NULL);
511 * If the entity has a ld_name, returns it if the dump_ld_name is set,
512 * else returns the name of the entity.
514 static const char *_get_ent_dump_name(ir_entity *ent, int dump_ld_name) {
516 return "<NULL entity>";
518 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
519 if (ent->ld_name) return get_id_str(ent->ld_name);
521 return get_id_str(ent->name);
525 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
526 * else returns the name of the entity.
528 const char *get_ent_dump_name(ir_entity *ent) {
529 return _get_ent_dump_name(ent, dump_ld_name);
532 /* Returns the name of an IRG. */
533 const char *get_irg_dump_name(ir_graph *irg) {
534 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
535 return _get_ent_dump_name(get_irg_entity(irg), 1);
539 * Returns non-zero if a node is in floating state.
541 static int node_floats(ir_node *n) {
542 return ((get_irn_pinned(n) == op_pin_state_floats) &&
543 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
547 * Walker that visits the anchors
549 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
550 if (dump_anchors || (dump_new_edges_flag && edges_activated(irg))) {
551 irg_walk_anchors(irg, pre, post, env);
553 irg_walk_graph(irg, pre, post, env);
558 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
560 static void collect_node(ir_node * node, void *env) {
564 || get_irn_op(node) == op_Bad
565 || get_irn_op(node) == op_Unknown
566 || get_irn_op(node) == op_NoMem) {
567 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
568 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
569 ARR_APP1(ir_node *, arr, node);
570 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
572 ir_node * block = get_nodes_block(node);
575 /* this node is in a Bad block, so we must place it into the graph's list */
576 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
577 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
578 ARR_APP1(ir_node *, arr, node);
579 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
581 ird_set_irn_link(node, ird_get_irn_link(block));
582 ird_set_irn_link(block, node);
587 /** Construct lists to walk ir block-wise.
589 * Collects all blocks, nodes not op_pin_state_pinned,
590 * Bad, NoMem and Unknown into a flexible array in link field of
591 * irg they belong to. Sets the irg link field to NULL in all
592 * graphs not visited.
593 * Free the list with DEL_ARR_F().
595 static ir_node **construct_block_lists(ir_graph *irg) {
597 #ifdef INTERPROCEDURAL_VIEW
598 int rem_view = get_interprocedural_view();
600 int walk_flag = using_visited(irg);
601 ir_graph *rem = current_ir_graph;
603 current_ir_graph = irg;
606 clear_using_visited(current_ir_graph);
608 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
609 ird_set_irg_link(get_irp_irg(i), NULL);
611 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
613 #ifdef INTERPROCEDURAL_VIEW
614 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
615 set_interprocedural_view(0);
618 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
619 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
620 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
621 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
623 #ifdef INTERPROCEDURAL_VIEW
624 set_interprocedural_view(rem_view);
628 set_using_visited(current_ir_graph);
630 current_ir_graph = rem;
631 return ird_get_irg_link(irg);
634 typedef struct _list_tuple {
636 ir_extblk **extbb_list;
639 /** Construct lists to walk IR extended block-wise.
640 * Free the lists in the tuple with DEL_ARR_F().
641 * Sets the irg link field to NULL in all
642 * graphs not visited.
644 static list_tuple *construct_extblock_lists(ir_graph *irg) {
645 ir_node **blk_list = construct_block_lists(irg);
647 ir_graph *rem = current_ir_graph;
648 list_tuple *lists = xmalloc(sizeof(*lists));
650 current_ir_graph = irg;
652 lists->blk_list = NEW_ARR_F(ir_node *, 0);
653 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
655 inc_irg_block_visited(irg);
656 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
659 if (is_Block(blk_list[i])) {
660 ext = get_Block_extbb(blk_list[i]);
662 if (extbb_not_visited(ext)) {
663 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
664 mark_extbb_visited(ext);
667 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
671 current_ir_graph = rem;
672 ird_set_irg_link(irg, lists);
676 /*-----------------------------------------------------------------*/
677 /* Routines to dump information about a single ir node. */
678 /*-----------------------------------------------------------------*/
681 * dump the name of a node n to the File F.
683 int dump_node_opcode(FILE *F, ir_node *n)
686 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
688 /* call the dump_node operation if available */
690 return ops->dump_node(n, F, dump_node_opcode_txt);
692 /* implementation for default nodes */
693 switch (get_irn_opcode(n)) {
698 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
699 assert(res < (int) sizeof(buf) && "buffer to small for tarval_snprintf");
704 switch (get_SymConst_kind(n)) {
705 case symconst_addr_name:
706 /* don't use get_SymConst_ptr_info as it mangles the name. */
707 fprintf(F, "SymC %s", get_id_str(get_SymConst_name(n)));
709 case symconst_addr_ent:
710 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
712 case symconst_ofs_ent:
713 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
715 case symconst_type_tag:
716 fprintf(F, "SymC %s tag", get_type_name_ex(get_SymConst_type(n), &bad));
718 case symconst_type_size:
719 fprintf(F, "SymC %s size", get_type_name_ex(get_SymConst_type(n), &bad));
721 case symconst_type_align:
722 fprintf(F, "SymC %s align", get_type_name_ex(get_SymConst_type(n), &bad));
724 case symconst_enum_const:
725 fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
728 fprintf(F, "SymC %lu label", get_SymConst_label(n));
734 if (!get_interprocedural_view())
741 ir_node *pred = get_Proj_pred(n);
743 if (get_irn_opcode(pred) == iro_Cond
744 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
745 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
746 fprintf(F, "defProj");
754 if (get_interprocedural_view()) {
755 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
760 case iro_CallBegin: {
761 ir_node *addr = get_CallBegin_ptr(n);
762 ir_entity *ent = NULL;
763 if (get_irn_op(addr) == op_Sel)
764 ent = get_Sel_entity(addr);
765 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
766 ent = get_SymConst_entity(addr);
767 fprintf(F, "%s", get_irn_opname(n));
768 if (ent) fprintf(F, " %s", get_entity_name(ent));
772 if (get_Load_align(n) == align_non_aligned)
774 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
777 if (get_Store_align(n) == align_non_aligned)
779 fprintf(F, "%s", get_irn_opname(n));
782 fprintf(F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
785 if (get_Conv_strict(n))
786 fprintf(F, "strict");
787 fprintf(F, "%s", get_irn_opname(n));
790 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Div_resmode(n), &bad));
793 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), &bad));
796 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_DivMod_resmode(n), &bad));
801 fprintf(F, "%s", get_irn_opname(n));
808 * Dump the mode of a node n to a file F.
809 * Ignore modes that are "always known".
811 static int dump_node_mode(FILE *F, ir_node *n)
814 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
817 /* call the dump_node operation if available */
819 return ops->dump_node(n, F, dump_node_mode_txt);
821 /* default implementation */
822 iro = get_irn_opcode(n);
834 ir_mode *mode = get_irn_mode(n);
836 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
837 (mode != mode_T || iro == iro_Proj))
838 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
846 * Dump the type of a node n to a file F if it's known.
848 static int dump_node_typeinfo(FILE *F, ir_node *n) {
851 if (opt_dump_analysed_type_info) {
852 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
853 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
854 ir_type *tp = get_irn_typeinfo_type(n);
855 if (tp != firm_none_type)
856 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
864 typedef struct _pns_lookup {
865 long nr; /**< the proj number */
866 const char *name; /**< the name of the Proj */
869 typedef struct _proj_lookup {
870 ir_opcode code; /**< the opcode of the Proj predecessor */
871 unsigned num_data; /**< number of data entries */
872 const pns_lookup_t *data; /**< the data */
875 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
877 /** the lookup table for Proj(Start) names */
878 static const pns_lookup_t start_lut[] = {
879 #define X(a) { pn_Start_##a, #a }
889 /** the lookup table for Proj(Cond) names */
890 static const pns_lookup_t cond_lut[] = {
891 #define X(a) { pn_Cond_##a, #a }
897 /** the lookup table for Proj(Call) names */
898 static const pns_lookup_t call_lut[] = {
899 #define X(a) { pn_Call_##a, #a }
909 /** the lookup table for Proj(Quot) names */
910 static const pns_lookup_t quot_lut[] = {
911 #define X(a) { pn_Quot_##a, #a }
919 /** the lookup table for Proj(DivMod) names */
920 static const pns_lookup_t divmod_lut[] = {
921 #define X(a) { pn_DivMod_##a, #a }
930 /** the lookup table for Proj(Div) names */
931 static const pns_lookup_t div_lut[] = {
932 #define X(a) { pn_Div_##a, #a }
940 /** the lookup table for Proj(Mod) names */
941 static const pns_lookup_t mod_lut[] = {
942 #define X(a) { pn_Mod_##a, #a }
950 /** the lookup table for Proj(Load) names */
951 static const pns_lookup_t load_lut[] = {
952 #define X(a) { pn_Load_##a, #a }
960 /** the lookup table for Proj(Store) names */
961 static const pns_lookup_t store_lut[] = {
962 #define X(a) { pn_Store_##a, #a }
969 /** the lookup table for Proj(Alloc) names */
970 static const pns_lookup_t alloc_lut[] = {
971 #define X(a) { pn_Alloc_##a, #a }
979 /** the lookup table for Proj(CopyB) names */
980 static const pns_lookup_t copyb_lut[] = {
981 #define X(a) { pn_CopyB_##a, #a }
989 /** the lookup table for Proj(InstOf) names */
990 static const pns_lookup_t instof_lut[] = {
991 #define X(a) { pn_InstOf_##a, #a }
1000 /** the lookup table for Proj(Raise) names */
1001 static const pns_lookup_t raise_lut[] = {
1002 #define X(a) { pn_Raise_##a, #a }
1008 /** the lookup table for Proj(Bound) names */
1009 static const pns_lookup_t bound_lut[] = {
1010 #define X(a) { pn_Bound_##a, #a }
1018 /** the Proj lookup table */
1019 static const proj_lookup_t proj_lut[] = {
1020 #define E(a) ARR_SIZE(a), a
1021 { iro_Start, E(start_lut) },
1022 { iro_Cond, E(cond_lut) },
1023 { iro_Call, E(call_lut) },
1024 { iro_Quot, E(quot_lut) },
1025 { iro_DivMod, E(divmod_lut) },
1026 { iro_Div, E(div_lut) },
1027 { iro_Mod, E(mod_lut) },
1028 { iro_Load, E(load_lut) },
1029 { iro_Store, E(store_lut) },
1030 { iro_Alloc, E(alloc_lut) },
1031 { iro_CopyB, E(copyb_lut) },
1032 { iro_InstOf, E(instof_lut) },
1033 { iro_Raise, E(raise_lut) },
1034 { iro_Bound, E(bound_lut) }
1039 * Dump additional node attributes of some nodes to a file F.
1042 dump_node_nodeattr(FILE *F, ir_node *n)
1048 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1050 /* call the dump_node operation if available */
1052 return ops->dump_node(n, F, dump_node_nodeattr_txt);
1054 switch (get_irn_opcode(n)) {
1056 if (0 && get_interprocedural_view()) {
1057 fprintf(F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
1062 pred = get_Proj_pred(n);
1063 proj_nr = get_Proj_proj(n);
1065 code = get_irn_opcode(pred);
1067 if (code == iro_Cmp)
1068 fprintf(F, "%s ", get_pnc_string(get_Proj_proj(n)));
1069 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1070 fprintf(F, "Arg %ld ", proj_nr);
1071 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1072 fprintf(F, "%ld ", proj_nr);
1074 unsigned i, j, f = 0;
1076 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
1077 if (code == proj_lut[i].code) {
1078 for (j = 0; j < proj_lut[i].num_data; ++j) {
1079 if (proj_nr == proj_lut[i].data[j].nr) {
1080 fprintf(F, "%s ", proj_lut[i].data[j].name);
1089 fprintf(F, "%ld ", proj_nr);
1090 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1091 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1092 fprintf(F, "PRED ");
1093 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1094 fprintf(F, "PRED ");
1099 proj_nr = get_Filter_proj(n);
1100 if (! get_interprocedural_view()) {
1102 pred = get_Filter_pred(n);
1105 fprintf(F, "%ld ", proj_nr);
1108 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1111 fprintf(F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1114 fprintf(F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1117 fprintf(F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1128 #include "execution_frequency.h"
1130 static void dump_node_ana_vals(FILE *F, ir_node *n) {
1134 #ifdef INTERPROCEDURAL_VIEW
1135 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1136 get_irn_exec_freq(n),
1137 get_irg_method_execution_frequency(get_irn_irg(n)),
1138 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1139 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1145 /* Dumps a node label without the enclosing ". */
1146 int dump_node_label(FILE *F, ir_node *n) {
1149 bad |= dump_node_opcode(F, n);
1150 bad |= dump_node_mode(F, n);
1152 bad |= dump_node_typeinfo(F, n);
1153 bad |= dump_node_nodeattr(F, n);
1154 if(dump_node_idx_labels) {
1155 fprintf(F, "%ld:%d", get_irn_node_nr(n), get_irn_idx(n));
1157 fprintf(F, "%ld", get_irn_node_nr(n));
1165 * Dumps the attributes of a node n into the file F.
1166 * Currently this is only the color of a node.
1168 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1173 print_vcg_color(F, ird_color_red);
1177 if (dump_node_vcgattr_hook)
1178 if (dump_node_vcgattr_hook(F, node, local))
1181 n = local ? local : node;
1183 if (overrule_nodecolor != ird_color_default) {
1184 print_vcg_color(F, overrule_nodecolor);
1188 switch (get_irn_opcode(n)) {
1195 print_vcg_color(F, ird_color_blue);
1198 if (is_Block_dead(n))
1199 print_vcg_color(F, ird_color_lightred);
1201 print_vcg_color(F, ird_color_lightyellow);
1204 print_vcg_color(F, ird_color_green);
1208 print_vcg_color(F, ird_color_gold);
1211 print_vcg_color(F, ird_color_orchid);
1217 print_vcg_color(F, ird_color_yellow);
1220 print_vcg_color(F, ird_color_darkyellow);
1223 PRINT_DEFAULT_NODE_ATTR;
1227 /* Adds a new node info dumper callback. */
1228 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1230 hook_entry_t *info = xmalloc(sizeof(*info));
1232 info->hook._hook_node_info = cb;
1233 info->context = data;
1234 register_hook(hook_node_info, info);
1239 /* Remove a previously added info dumper callback. */
1240 void dump_remv_node_info_callback(void *handle)
1242 hook_entry_t *info = handle;
1243 unregister_hook(hook_node_info, info);
1248 * Dump the node information of a node n to a file F.
1250 static INLINE int dump_node_info(FILE *F, ir_node *n)
1253 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1255 fprintf(F, " info1: \"");
1256 bad = dump_irnode_to_file(F, n);
1257 /* call the dump_node operation if available */
1259 bad = ops->dump_node(n, F, dump_node_info_txt);
1261 /* allow additional info to be added */
1262 hook_node_info(F, n);
1269 * checks whether a node is "constant-like" ie can be treated "block-less"
1272 int is_constlike_node(ir_node *n) {
1273 ir_opcode code = get_irn_opcode(n);
1274 return (code == iro_Const || code == iro_Bad || code == iro_NoMem || code == iro_SymConst || code == iro_Unknown);
1278 /** outputs the predecessors of n, that are constants, local. I.e.,
1279 generates a copy of the constant predecessors for each node called with. */
1280 static void dump_const_node_local(FILE *F, ir_node *n) {
1282 if (!get_opt_dump_const_local()) return;
1284 /* Use visited flag to avoid outputting nodes twice.
1285 initialize it first. */
1286 for (i = 0; i < get_irn_arity(n); i++) {
1287 ir_node *con = get_irn_n(n, i);
1288 if (is_constlike_node(con)) {
1289 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1293 for (i = 0; i < get_irn_arity(n); i++) {
1294 ir_node *con = get_irn_n(n, i);
1295 if (is_constlike_node(con) && irn_not_visited(con)) {
1298 mark_irn_visited(con);
1299 /* Generate a new name for the node by appending the names of
1301 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1302 fprintf(F, " label: \"");
1303 bad |= dump_node_label(F, con);
1305 bad |= dump_node_info(F, con);
1306 dump_node_vcgattr(F, n, con, bad);
1312 /** If the block of an edge is a const_like node, dump it local with an edge */
1313 static void dump_const_block_local(FILE *F, ir_node *n) {
1316 if (!get_opt_dump_const_local()) return;
1318 blk = get_nodes_block(n);
1319 if (is_constlike_node(blk)) {
1322 /* Generate a new name for the node by appending the names of
1324 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1325 fprintf(F, "\" label: \"");
1326 bad |= dump_node_label(F, blk);
1328 bad |= dump_node_info(F, blk);
1329 dump_node_vcgattr(F, n, blk, bad);
1332 fprintf(F, "edge: { sourcename: \"");
1334 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1336 if (dump_edge_vcgattr_hook) {
1338 if (dump_edge_vcgattr_hook(F, n, -1)) {
1342 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1347 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1352 * prints the error message of a node to a file F as info2.
1354 static void print_node_error(FILE *F, const char *err_msg)
1359 fprintf(F, " info2: \"%s\"", err_msg);
1363 * prints debug messages of a node to file F as info3.
1365 static void print_dbg_info(FILE *F, dbg_info *dbg)
1369 if (__dbg_info_snprint) {
1371 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1372 fprintf(F, " info3: \"%s\"\n", buf);
1379 static void dump_node(FILE *F, ir_node *n)
1384 if (get_opt_dump_const_local() && is_constlike_node(n))
1387 /* dump this node */
1388 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1390 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1391 bad |= dump_node_label(F, n);
1392 dump_node_ana_vals(F, n);
1393 //dump_node_ana_info(F, n);
1395 bad |= dump_node_info(F, n);
1396 print_node_error(F, p);
1397 print_dbg_info(F, get_irn_dbg_info(n));
1398 dump_node_vcgattr(F, n, NULL, bad);
1400 dump_const_node_local(F, n);
1402 if(dump_node_edge_hook)
1403 dump_node_edge_hook(F, n);
1405 dump_irn_chi_term(F, n);
1406 dump_irn_state(F, n);
1410 /** dump the edge to the block this node belongs to */
1412 dump_ir_block_edge(FILE *F, ir_node *n) {
1413 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1414 if (is_no_Block(n)) {
1415 ir_node *block = get_nodes_block(n);
1417 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1418 dump_const_block_local(F, n);
1420 fprintf(F, "edge: { sourcename: \"");
1422 fprintf(F, "\" targetname: ");
1423 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1425 if (dump_edge_vcgattr_hook) {
1427 if (dump_edge_vcgattr_hook(F, n, -1)) {
1431 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1436 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1442 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1444 * do not use get_nodes_block() here, will fail
1445 * if the irg is not pinned.
1447 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1448 fprintf(F, INTRA_DATA_EDGE_ATTR);
1450 fprintf(F, INTER_DATA_EDGE_ATTR);
1454 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1456 * do not use get_nodes_block() here, will fail
1457 * if the irg is not pinned.
1459 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1460 fprintf(F, INTRA_MEM_EDGE_ATTR);
1462 fprintf(F, INTER_MEM_EDGE_ATTR);
1465 /** Print the vcg attributes for the edge from node from to it's to's input */
1466 static void print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1469 if (dump_edge_vcgattr_hook)
1470 if (dump_edge_vcgattr_hook(F, from, to))
1473 if (dump_backedge_information_flag && is_backedge(from, to))
1474 fprintf(F, BACK_EDGE_ATTR);
1476 switch (get_irn_opcode(from)) {
1478 fprintf(F, CF_EDGE_ATTR);
1480 case iro_Start: break;
1483 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1484 fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
1486 fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
1490 if (is_Proj(from)) {
1491 if (get_irn_mode(from) == mode_M)
1492 print_mem_edge_vcgattr(F, from, to);
1493 else if (get_irn_mode(from) == mode_X)
1494 fprintf(F, CF_EDGE_ATTR);
1496 print_data_edge_vcgattr(F, from, to);
1498 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1499 print_mem_edge_vcgattr(F, from, to);
1500 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1501 fprintf(F, CF_EDGE_ATTR);
1503 print_data_edge_vcgattr(F, from, to);
1507 /** dump edges to our inputs */
1508 static void dump_ir_data_edges(FILE *F, ir_node *n) {
1510 unsigned long visited = get_irn_visited(n);
1512 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1515 /* dump the dependency edges. */
1516 for (i = 0; i < get_irn_deps(n); ++i) {
1517 ir_node *dep = get_irn_dep(n, i);
1520 fprintf(F, "edge: {sourcename: \"");
1522 fprintf(F, "\" targetname: ");
1523 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1524 PRINT_CONSTID(n, dep);
1530 fprintf(F, " label: \"%d\" ", i);
1531 fprintf(F, " color: darkgreen}\n");
1535 for (i = 0; i < get_irn_arity(n); i++) {
1536 ir_node * pred = get_irn_n(n, i);
1539 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1540 continue; /* pred not dumped */
1542 if (dump_backedge_information_flag && is_backedge(n, i))
1543 fprintf(F, "backedge: {sourcename: \"");
1545 fprintf(F, "edge: {sourcename: \"");
1547 fprintf(F, "\" targetname: ");
1548 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1549 PRINT_CONSTID(n, pred);
1551 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1553 fprintf(F, " label: \"%d\" ", i);
1554 print_edge_vcgattr(F, n, i);
1563 dump_ir_edges(FILE *F, ir_node *n) {
1564 const ir_edge_t *edge;
1567 foreach_out_edge(n, edge) {
1568 ir_node *succ = get_edge_src_irn(edge);
1570 fprintf(F, "edge: {sourcename: \"");
1572 fprintf(F, "\" targetname: \"");
1576 fprintf(F, " label: \"%d\" ", i);
1577 fprintf(F, OUT_EDGE_ATTR);
1584 /** Dumps a node and its edges but not the block edge
1587 dump_node_wo_blockedge(ir_node *n, void *env) {
1590 dump_ir_data_edges(F, n);
1593 /** Dumps a node and its edges.
1596 dump_whole_node(ir_node *n, void *env) {
1598 dump_node_wo_blockedge(n, env);
1599 if (!node_floats(n))
1600 dump_ir_block_edge(F, n);
1601 if (dump_new_edges_flag && edges_activated(current_ir_graph))
1602 dump_ir_edges(F, n);
1606 dump_const_node(ir_node *n, void *env) {
1607 if (is_Block(n)) return;
1608 dump_node_wo_blockedge(n, env);
1611 /***********************************************************************/
1612 /* the following routines dump the nodes/irgs bracketed to graphs. */
1613 /***********************************************************************/
1615 /** Dumps a constant expression as entity initializer, array bound ...
1617 static void dump_const_expression(FILE *F, ir_node *value) {
1618 ir_graph *rem = current_ir_graph;
1619 int rem_dump_const_local = dump_const_local;
1620 dump_const_local = 0;
1621 current_ir_graph = get_const_code_irg();
1622 irg_walk(value, dump_const_node, NULL, F);
1623 /* Decrease visited flag so that we walk with the same flag for the next
1624 expression. This guarantees that we don't dump the same node twice,
1625 as for const expressions cse is performed to save memory. */
1626 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1627 current_ir_graph = rem;
1628 dump_const_local = rem_dump_const_local;
1631 /** Dump a block as graph containing its nodes.
1633 * Expects to find nodes belonging to the block as list in its
1635 * Dumps the edges of all nodes including itself. */
1637 dump_whole_block(FILE *F, ir_node *block) {
1639 dumper_colors color = ird_color_yellow;
1641 assert(is_Block(block));
1643 fprintf(F, "graph: { title: \"");
1644 PRINT_NODEID(block);
1645 fprintf(F, "\" label: \"");
1646 dump_node_label(F, block);
1648 if (get_opt_dump_abstvals())
1649 fprintf(F, " seqno: %d", (int)get_Block_seqno(block));
1652 /* colorize blocks */
1653 if (! get_Block_matured(block))
1654 color = ird_color_red;
1655 if (is_Block_dead(block))
1656 color = ird_color_orange;
1658 fprintf(F, "\" status:clustered ");
1659 print_vcg_color(F, color);
1662 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1663 dump_node_info(F, block);
1664 print_dbg_info(F, get_irn_dbg_info(block));
1666 /* dump the blocks edges */
1667 dump_ir_data_edges(F, block);
1669 if (dump_block_edge_hook)
1670 dump_block_edge_hook(F, block);
1672 /* dump the nodes that go into the block */
1673 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1675 dump_ir_data_edges(F, node);
1678 /* Close the vcg information for the block */
1680 dump_const_node_local(F, block);
1682 dump_irn_chi_term(F, block);
1687 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1688 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1690 dump_block_graph(FILE *F, ir_graph *irg) {
1692 ir_graph *rem = current_ir_graph;
1693 ir_node **arr = ird_get_irg_link(irg);
1694 current_ir_graph = irg;
1696 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1697 ir_node * node = arr[i];
1698 if (is_Block(node)) {
1699 /* Dumps the block and all the nodes in the block, which are to
1700 be found in Block->link. */
1701 dump_whole_block(F, node);
1703 /* Nodes that are not in a Block. */
1705 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1706 dump_const_block_local(F, node);
1708 dump_ir_data_edges(F, node);
1710 if (dump_new_edges_flag && edges_activated(irg))
1711 dump_ir_edges(F, node);
1714 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1715 dump_loop_nodes_into_graph(F, irg);
1717 current_ir_graph = rem;
1721 * Dump the info for an irg.
1722 * Parsed by XVCG but not shown. use yComp.
1724 static void dump_graph_info(FILE *F, ir_graph *irg) {
1725 fprintf(F, "info1: \"");
1726 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1730 /** Dumps an irg as a graph clustered by block nodes.
1731 * If interprocedural view edges can point to nodes out of this graph.
1733 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1734 ir_entity *ent = get_irg_entity(irg);
1736 fprintf(F, "graph: { title: \"");
1738 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1739 get_ent_dump_name(ent));
1741 dump_graph_info(F, irg);
1742 print_dbg_info(F, get_entity_dbg_info(ent));
1744 dump_block_graph(F, irg);
1746 /* Close the vcg information for the irg */
1747 fprintf(F, "}\n\n");
1750 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1751 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1753 dump_extblock_graph(FILE *F, ir_graph *irg) {
1755 ir_graph *rem = current_ir_graph;
1756 ir_extblk **arr = ird_get_irg_link(irg);
1757 current_ir_graph = irg;
1759 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1760 ir_extblk *extbb = arr[i];
1761 ir_node *leader = get_extbb_leader(extbb);
1764 fprintf(F, "graph: { title: \"");
1765 PRINT_EXTBBID(leader);
1766 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1767 get_irn_node_nr(leader));
1769 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1770 ir_node * node = extbb->blks[j];
1771 if (is_Block(node)) {
1772 /* Dumps the block and all the nodes in the block, which are to
1773 be found in Block->link. */
1774 dump_whole_block(F, node);
1776 /* Nodes that are not in a Block. */
1778 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1779 dump_const_block_local(F, node);
1781 dump_ir_data_edges(F, node);
1787 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1788 dump_loop_nodes_into_graph(F, irg);
1790 current_ir_graph = rem;
1795 /*******************************************************************/
1796 /* Basic type and entity nodes and edges. */
1797 /*******************************************************************/
1799 /** dumps the edges between nodes and their type or entity attributes. */
1800 static void dump_node2type_edges(ir_node *n, void *env)
1805 switch (get_irn_opcode(n)) {
1807 /* @@@ some consts have an entity */
1810 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1811 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1814 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1817 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1820 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1823 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1826 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1834 static int print_type_info(FILE *F, ir_type *tp) {
1837 if (get_type_state(tp) == layout_undefined) {
1838 fprintf(F, "state: layout_undefined\n");
1840 fprintf(F, "state: layout_fixed,\n");
1842 if (get_type_mode(tp))
1843 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1844 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1849 static void print_typespecific_info(FILE *F, ir_type *tp) {
1850 switch (get_type_tpop_code(tp)) {
1852 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1857 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1858 fprintf(F, "params: %d\n", get_method_n_params(tp));
1859 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1865 case tpo_enumeration:
1877 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1878 switch (get_type_tpop_code(tp)) {
1880 if (peculiarity_existent == get_class_peculiarity(tp))
1881 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1883 fprintf(F, " " TYPE_DESCRIPTION_NODE_ATTR);
1886 fprintf(F, " " TYPE_METH_NODE_ATTR);
1894 case tpo_enumeration:
1906 int dump_type_node(FILE *F, ir_type *tp)
1910 fprintf(F, "node: {title: ");
1912 fprintf(F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1913 fprintf(F, " info1: \"");
1915 bad |= print_type_info(F, tp);
1916 print_typespecific_info(F, tp);
1918 dump_type_to_file(F, tp, dump_verbosity_max);
1921 print_dbg_info(F, get_type_dbg_info(tp));
1922 print_typespecific_vcgattr(F, tp);
1929 void dump_entity_node(FILE *F, ir_entity *ent, int color)
1931 fprintf(F, "node: {title: \"");
1932 PRINT_ENTID(ent); fprintf(F, "\"");
1933 fprintf(F, DEFAULT_TYPE_ATTRIBUTE);
1934 fprintf(F, "label: ");
1935 fprintf(F, "\"ent %s\" ", get_ent_dump_name(ent));
1937 fprintf(F, "color:%d", color);
1939 fprintf(F, ENTITY_NODE_ATTR);
1940 fprintf(F, "\n info1: \"");
1942 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1945 print_dbg_info(F, get_entity_dbg_info(ent));
1949 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1952 ir_enum_const *ec = get_enumeration_const(tp, pos);
1953 ident *id = get_enumeration_nameid(ec);
1954 tarval *tv = get_enumeration_value(ec);
1957 tarval_snprintf(buf, sizeof(buf), tv);
1959 strncpy(buf, "<not set>", sizeof(buf));
1960 fprintf(F, "node: {title: \"");
1961 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1962 fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1963 fprintf(F, "label: ");
1964 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1965 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1968 /* dumps a type or entity and it's edges. */
1970 dump_type_info(type_or_ent *tore, void *env) {
1972 int i = 0; /* to shutup gcc */
1974 /* dump this type or entity */
1976 switch (get_kind(tore)) {
1978 ir_entity *ent = (ir_entity *)tore;
1981 dump_entity_node(F, ent, 0);
1983 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1984 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1985 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1986 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1987 if (is_Class_type(get_entity_owner(ent))) {
1988 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1989 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1991 /* attached subgraphs */
1992 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1993 if (is_atomic_entity(ent)) {
1994 value = get_atomic_ent_value(ent);
1996 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1997 /* DDMN(value); $$$ */
1998 dump_const_expression(F, value);
2001 if (is_compound_entity(ent)) {
2002 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
2003 value = get_compound_ent_value(ent, i);
2005 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
2006 dump_const_expression(F, value);
2007 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
2009 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
2010 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
2011 get_compound_ent_value_member(ent, i), i);
2020 ir_type *tp = (ir_type *)tore;
2021 dump_type_node(F, tp);
2022 /* and now the edges */
2023 switch (get_type_tpop_code(tp)) {
2025 for (i=0; i < get_class_n_supertypes(tp); i++)
2026 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2027 for (i=0; i < get_class_n_members(tp); i++)
2028 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
2031 for (i=0; i < get_struct_n_members(tp); i++)
2032 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
2035 for (i = 0; i < get_method_n_params(tp); i++)
2036 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
2037 for (i = 0; i < get_method_n_ress(tp); i++)
2038 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
2041 for (i = 0; i < get_union_n_members(tp); i++)
2042 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
2045 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
2046 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
2047 for (i = 0; i < get_array_n_dimensions(tp); i++) {
2048 ir_node *upper = get_array_upper_bound(tp, i);
2049 ir_node *lower = get_array_lower_bound(tp, i);
2050 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
2051 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
2052 dump_const_expression(F, upper);
2053 dump_const_expression(F, lower);
2056 case tpo_enumeration:
2057 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
2058 dump_enum_item(F, tp, i);
2059 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
2063 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
2070 break; /* case k_type */
2073 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
2074 } /* switch kind_or_entity */
2077 typedef struct _h_env {
2082 /** For dumping class hierarchies.
2083 * Dumps a class type node and a superclass edge.
2084 * If env->dump_ent dumps entities of classes and overwrites edges.
2087 dump_class_hierarchy_node(type_or_ent *tore, void *ctx) {
2090 int i = 0; /* to shutup gcc */
2092 /* dump this type or entity */
2093 switch (get_kind(tore)) {
2095 ir_entity *ent = (ir_entity *)tore;
2096 if (get_entity_owner(ent) == get_glob_type()) break;
2097 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
2098 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2100 dump_entity_node(F, ent, 0);
2102 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
2103 for(i = 0; i < get_entity_n_overwrites(ent); i++)
2104 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
2109 ir_type *tp = (ir_type *)tore;
2110 if (tp == get_glob_type()) break;
2111 switch (get_type_tpop_code(tp)) {
2113 dump_type_node(F, tp);
2114 /* and now the edges */
2115 for (i=0; i < get_class_n_supertypes(tp); i++) {
2116 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2121 break; /* case k_type */
2124 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2125 } /* switch kind_or_entity */
2128 /*******************************************************************/
2129 /* dump analysis information that is expressed in graph terms. */
2130 /*******************************************************************/
2132 /* dump out edges */
2134 dump_out_edge(ir_node *n, void *env) {
2137 for (i = 0; i < get_irn_n_outs(n); i++) {
2138 assert(get_irn_out(n, i));
2139 fprintf(F, "edge: {sourcename: \"");
2141 fprintf(F, "\" targetname: \"");
2142 PRINT_NODEID(get_irn_out(n, i));
2143 fprintf(F, "\" color: red linestyle: dashed");
2149 dump_loop_label(FILE *F, ir_loop *loop) {
2150 fprintf(F, "loop %d, %d sons, %d nodes",
2151 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2154 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2155 fprintf(F, " info1: \"");
2156 fprintf(F, " loop nr: %d", get_loop_loop_nr(loop));
2157 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
2158 fprintf(F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2164 dump_loop_node(FILE *F, ir_loop *loop) {
2165 fprintf(F, "node: {title: \"");
2167 fprintf(F, "\" label: \"");
2168 dump_loop_label(F, loop);
2170 dump_loop_info(F, loop);
2175 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2177 fprintf(F, "edge: {sourcename: \"");
2179 fprintf(F, "\" targetname: \"");
2180 PRINT_NODEID(get_loop_node(loop, i));
2181 fprintf(F, "\" color: green");
2186 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2188 fprintf(F, "edge: {sourcename: \"");
2190 fprintf(F, "\" targetname: \"");
2191 PRINT_LOOPID(get_loop_son(loop, i));
2192 fprintf(F, "\" color: darkgreen label: \"%d\"}\n",
2193 get_loop_element_pos(loop, get_loop_son(loop, i)));
2197 void dump_loops(FILE *F, ir_loop *loop) {
2199 /* dump this loop node */
2200 dump_loop_node(F, loop);
2202 /* dump edges to nodes in loop -- only if it is a real loop */
2203 if (get_loop_depth(loop) != 0) {
2204 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2205 dump_loop_node_edge(F, loop, i);
2208 for (i = 0; i < get_loop_n_sons(loop); i++) {
2209 dump_loops(F, get_loop_son(loop, i));
2210 dump_loop_son_edge(F, loop, i);
2215 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2216 ir_graph *rem = current_ir_graph;
2217 current_ir_graph = irg;
2219 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2221 current_ir_graph = rem;
2226 * dumps the VCG header
2228 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2237 if (!orientation) orientation = "bottom_to_top";
2241 "graph: { title: \"ir graph of %s\"\n"
2242 "display_edge_labels: %s\n"
2243 "layoutalgorithm: mindepth\n"
2244 "manhattan_edges: yes\n"
2245 "port_sharing: no\n"
2247 "classname 1: \"intrablock Data\"\n"
2248 "classname 2: \"Block\"\n"
2249 "classname 3: \"Entity type\"\n"
2250 "classname 4: \"Entity owner\"\n"
2251 "classname 5: \"Method Param\"\n"
2252 "classname 6: \"Method Res\"\n"
2253 "classname 7: \"Super\"\n"
2254 "classname 8: \"Union\"\n"
2255 "classname 9: \"Points-to\"\n"
2256 "classname 10: \"Array Element Type\"\n"
2257 "classname 11: \"Overwrites\"\n"
2258 "classname 12: \"Member\"\n"
2259 "classname 13: \"Control Flow\"\n"
2260 "classname 14: \"intrablock Memory\"\n"
2261 "classname 15: \"Dominators\"\n"
2262 "classname 16: \"interblock Data\"\n"
2263 "classname 17: \"interblock Memory\"\n"
2264 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2265 "classname 19: \"Postdominators\"\n"
2266 "classname 20: \"Keep Alive\"\n"
2267 "classname 21: \"Out Edges\"\n"
2268 "infoname 1: \"Attribute\"\n"
2269 "infoname 2: \"Verification errors\"\n"
2270 "infoname 3: \"Debug info\"\n",
2271 name, label, orientation);
2273 /* don't use all, the range is too wide. */
2277 "colorentry 100: 0 0 0\n"
2278 "colorentry 101: 20 0 0\n"
2279 "colorentry 102: 40 0 0\n"
2280 "colorentry 103: 60 0 0\n"
2281 "colorentry 104: 80 0 0\n"
2282 "colorentry 105: 100 0 0\n"
2283 "colorentry 106: 120 0 0\n"
2284 "colorentry 107: 140 0 0\n"
2285 "colorentry 108: 150 0 0\n"
2286 "colorentry 109: 180 0 0\n"
2287 "colorentry 110: 200 0 0\n"
2288 "colorentry 111: 220 0 0\n"
2289 "colorentry 112: 240 0 0\n"
2290 "colorentry 113: 255 0 0\n"
2291 "colorentry 113: 255 20 20\n"
2292 "colorentry 114: 255 40 40\n"
2293 "colorentry 115: 255 60 60\n"
2294 "colorentry 116: 255 80 80\n"
2295 "colorentry 117: 255 100 100\n"
2296 "colorentry 118: 255 120 120\n"
2297 "colorentry 119: 255 140 140\n"
2298 "colorentry 120: 255 150 150\n"
2299 "colorentry 121: 255 180 180\n"
2300 "colorentry 122: 255 200 200\n"
2301 "colorentry 123: 255 220 220\n"
2302 "colorentry 124: 255 240 240\n"
2303 "colorentry 125: 255 250 250\n"
2306 fprintf(F, "\n"); /* a separator */
2312 * @param irg The graph to be dumped
2313 * @param suffix1 first filename suffix
2314 * @param suffix2 second filename suffix
2316 FILE *vcg_open(ir_graph *irg, const char * suffix1, const char *suffix2) {
2318 const char *nm = get_irg_dump_name(irg);
2319 int len = strlen(nm), i, j;
2320 char *fname; /* filename to put the vcg information in */
2322 if (!suffix1) suffix1 = "";
2323 if (!suffix2) suffix2 = "";
2325 /* open file for vcg graph */
2326 fname = xmalloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2328 /* strncpy (fname, nm, len); */ /* copy the filename */
2330 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2332 fname[j] = '@'; j++; fname[j] = '1'; j++;
2333 } else if (nm[i] == '@') {
2334 fname[j] = '@'; j++; fname[j] = '2'; j++;
2336 fname[j] = nm[i]; j++;
2340 strcat(fname, suffix1); /* append file suffix */
2341 strcat(fname, suffix2); /* append file suffix */
2342 strcat(fname, ".vcg"); /* append the .vcg suffix */
2344 /* vcg really expect only a <CR> at end of line, so
2345 * the "b"inary mode is what you mean (and even needed for Win32)
2347 F = fopen(fname, "wb"); /* open file for writing */
2359 * @param name prefix file name
2360 * @param suffix filename suffix
2362 FILE *vcg_open_name(const char *name, const char *suffix) {
2364 char *fname; /* filename to put the vcg information in */
2365 int i, j, len = strlen(name);
2367 if (!suffix) suffix = "";
2369 /** open file for vcg graph */
2370 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2371 /* strcpy (fname, name);*/ /* copy the filename */
2373 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2374 if (name[i] == '/') {
2375 fname[j] = '@'; j++; fname[j] = '1'; j++;
2376 } else if (name[i] == '@') {
2377 fname[j] = '@'; j++; fname[j] = '2'; j++;
2379 fname[j] = name[i]; j++;
2383 strcat(fname, suffix);
2384 strcat(fname, ".vcg"); /* append the .vcg suffix */
2386 /* vcg really expect only a <CR> at end of line, so
2387 * the "b"inary mode is what you mean (and even needed for Win32)
2389 F = fopen(fname, "wb"); /* open file for writing */
2399 * Dumps the vcg file footer
2401 static void dump_vcg_footer(FILE *F) {
2406 * close the vcg file
2408 void vcg_close(FILE *F) {
2409 dump_vcg_footer(F); /* print footer */
2410 fclose (F); /* close vcg file */
2413 /************************************************************************/
2414 /************************************************************************/
2415 /* Routines that dump all or parts of the firm representation to a file */
2416 /************************************************************************/
2417 /************************************************************************/
2419 /************************************************************************/
2420 /* Dump ir graphs, different formats and additional information. */
2421 /************************************************************************/
2423 /** Routine to dump a graph, blocks as conventional nodes. */
2425 dump_ir_graph(ir_graph *irg, const char *suffix )
2431 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2434 if (dump_backedge_information_flag && get_irg_loopinfo_state(irg) != loopinfo_consistent) {
2435 construct_backedges(irg);
2438 rem = current_ir_graph;
2439 current_ir_graph = irg;
2440 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2441 else suffix1 = "-pure";
2442 f = vcg_open(irg, suffix, suffix1);
2444 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2446 /* call the dump graph hook */
2447 if (dump_ir_graph_hook)
2448 if (dump_ir_graph_hook(f, irg)) {
2449 current_ir_graph = rem;
2453 /* walk over the graph */
2454 /* dump_whole_node must be called in post visiting predecessors */
2455 ird_walk_graph(irg, NULL, dump_whole_node, f);
2457 /* dump the out edges in a separate walk */
2458 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2459 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2464 current_ir_graph = rem;
2467 /* Dump a firm graph without explicit block nodes. */
2468 void dump_ir_block_graph(ir_graph *irg, const char *suffix)
2474 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2477 if (get_interprocedural_view()) suffix1 = "-ip";
2479 f = vcg_open(irg, suffix, suffix1);
2482 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2484 construct_block_lists(irg);
2487 * If we are in the interprocedural view, we dump not
2488 * only the requested irg but also all irgs that can be reached
2491 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2492 ir_graph *g = get_irp_irg(i);
2493 ir_node **arr = ird_get_irg_link(g);
2495 dump_graph_from_list(f, g);
2504 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2505 void dump_ir_extblock_graph(ir_graph *irg, const char *suffix)
2512 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2515 if (get_irg_extblk_state(irg) != extblk_valid)
2518 if (get_interprocedural_view()) suffix1 = "-ip";
2521 ent = get_irg_entity(irg);
2523 F = vcg_open(irg, suffix, suffix1);
2525 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2527 construct_extblock_lists(irg);
2529 fprintf(F, "graph: { title: \"");
2531 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2532 get_ent_dump_name(ent));
2534 dump_graph_info(F, irg);
2535 print_dbg_info(F, get_entity_dbg_info(ent));
2537 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2538 ir_graph *irg = get_irp_irg(i);
2539 list_tuple *lists = ird_get_irg_link(irg);
2542 /* dump the extended blocks first */
2543 if (ARR_LEN(lists->extbb_list)) {
2544 ird_set_irg_link(irg, lists->extbb_list);
2545 dump_extblock_graph(F, irg);
2548 /* we may have blocks without extended blocks, bad for instance */
2549 if (ARR_LEN(lists->blk_list)) {
2550 ird_set_irg_link(irg, lists->blk_list);
2551 dump_block_graph(F, irg);
2554 DEL_ARR_F(lists->extbb_list);
2555 DEL_ARR_F(lists->blk_list);
2560 /* Close the vcg information for the irg */
2561 fprintf(F, "}\n\n");
2568 /* dumps a graph with type information */
2570 dump_ir_graph_w_types(ir_graph *irg, const char *suffix)
2575 /* if a filter is set, dump only the irg's that match the filter */
2576 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2579 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2580 else suffix1 = "-pure-wtypes";
2581 f = vcg_open(irg,suffix, suffix1);
2583 ir_graph *rem = current_ir_graph;
2584 int rem_dump_const_local;
2586 current_ir_graph = irg;
2587 rem_dump_const_local = dump_const_local;
2588 /* dumping types does not work with local nodes */
2589 dump_const_local = 0;
2591 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2593 /* dump common ir graph */
2594 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2595 /* dump type info */
2596 type_walk_irg(irg, dump_type_info, NULL, f);
2597 inc_irg_visited(get_const_code_irg());
2598 /* dump edges from graph to type info */
2599 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2602 dump_const_local = rem_dump_const_local;
2603 current_ir_graph = rem;
2608 dump_ir_block_graph_w_types(ir_graph *irg, const char *suffix)
2614 /* if a filter is set, dump only the irg's that match the filter */
2615 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2618 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2619 else suffix1 = "-wtypes";
2620 f = vcg_open(irg, suffix, suffix1);
2622 ir_graph *rem = current_ir_graph;
2623 int rem_dump_const_local;
2625 rem_dump_const_local = dump_const_local;
2626 /* dumping types does not work with local nodes */
2627 dump_const_local = 0;
2629 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2631 /* dump common blocked ir graph */
2632 construct_block_lists(irg);
2634 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2635 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2637 dump_graph_from_list(f, get_irp_irg(i));
2642 /* dump type info */
2643 current_ir_graph = irg;
2644 type_walk_irg(irg, dump_type_info, NULL, f);
2645 inc_irg_visited(get_const_code_irg());
2647 /* dump edges from graph to type info */
2648 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2651 dump_const_local = rem_dump_const_local;
2652 current_ir_graph = rem;
2656 /*---------------------------------------------------------------------*/
2657 /* The following routines dump a control flow graph. */
2658 /*---------------------------------------------------------------------*/
2661 dump_block_to_cfg(ir_node *block, void *env) {
2666 if (is_Block(block)) {
2667 /* This is a block. Dump a node for the block. */
2668 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2669 fprintf(F, "\" label: \"");
2670 if (block == get_irg_start_block(get_irn_irg(block)))
2671 fprintf(F, "Start ");
2672 if (block == get_irg_end_block(get_irn_irg(block)))
2675 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2676 PRINT_NODEID(block);
2678 fprintf(F, "info1:\"");
2680 /* the generic version. */
2681 dump_irnode_to_file(F, block);
2683 /* Check whether we have bad predecessors to color the block. */
2684 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2685 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2688 fprintf(F, "\""); /* closing quote of info */
2690 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2691 (block == get_irg_end_block(get_irn_irg(block))) )
2692 fprintf(F, " color:blue ");
2694 fprintf(F, " color:yellow ");
2697 /* Dump the edges */
2698 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2699 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2700 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2701 fprintf(F, "edge: { sourcename: \"");
2702 PRINT_NODEID(block);
2703 fprintf(F, "\" targetname: \"");
2705 fprintf(F, "\"}\n");
2708 /* Dump dominator/postdominator edge */
2709 if (dump_dominator_information_flag) {
2710 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2711 pred = get_Block_idom(block);
2712 fprintf(F, "edge: { sourcename: \"");
2713 PRINT_NODEID(block);
2714 fprintf(F, "\" targetname: \"");
2716 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2718 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2719 pred = get_Block_ipostdom(block);
2720 fprintf(F, "edge: { sourcename: \"");
2721 PRINT_NODEID(block);
2722 fprintf(F, "\" targetname: \"");
2724 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2731 dump_cfg(ir_graph *irg, const char *suffix)
2734 /* if a filter is set, dump only the irg's that match the filter */
2735 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2738 f = vcg_open(irg, suffix, "-cfg");
2740 ir_graph *rem = current_ir_graph;
2741 #ifdef INTERPROCEDURAL_VIEW
2742 int ipv = get_interprocedural_view();
2745 current_ir_graph = irg;
2746 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2748 #ifdef INTERPROCEDURAL_VIEW
2750 printf("Warning: dumping cfg not in interprocedural view!\n");
2751 set_interprocedural_view(0);
2755 /* walk over the blocks in the graph */
2756 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2757 dump_node(f, get_irg_bad(irg));
2759 #ifdef INTERPROCEDURAL_VIEW
2760 set_interprocedural_view(ipv);
2763 current_ir_graph = rem;
2768 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2769 if (pset_find_ptr(mark_set, n)) return;
2771 pset_insert_ptr(mark_set, n);
2774 int i, start = is_Block(n) ? 0 : -1;
2775 dump_whole_node(n, F);
2776 for (i = start; i < get_irn_arity(n); ++i)
2777 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2780 /* Don't dump edges to nodes further out. These might be edges to
2781 nodes we already dumped, if there is a shorter path to these. */
2785 static int subgraph_counter = 0;
2786 void dump_subgraph(ir_node *root, int depth, const char *suffix) {
2790 sprintf(buf, "-subg_%03d", subgraph_counter++);
2791 F = vcg_open(get_irn_irg(root), suffix, buf);
2793 pset *mark_set = pset_new_ptr(1);
2794 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2795 descend_and_dump(F, root, depth, mark_set);
2802 static int weight_overall(int rec, int loop) {
2803 return 2*rec + loop;
2806 static int compute_color(int my, int max) {
2813 /* if small, scale to the full color range. */
2815 my = my * (n_colors/max);
2817 step = 1 + (max / n_colors);
2821 return base_color + n_colors - color;
2825 * Calculate a entity color depending on it's execution propability.
2827 static int get_entity_color(ir_entity *ent) {
2828 ir_graph *irg = get_entity_irg(ent);
2832 int rec_depth = get_irg_recursion_depth(irg);
2833 int loop_depth = get_irg_loop_depth(irg);
2834 int overall_depth = weight_overall(rec_depth, loop_depth);
2836 int max_rec_depth = irp->max_callgraph_recursion_depth;
2837 int max_loop_depth = irp->max_callgraph_loop_depth;
2838 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2840 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2841 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2842 int my_overall_color = compute_color(overall_depth, max_overall_depth);
2844 return my_overall_color;
2849 #ifdef INTERPROCEDURAL_VIEW
2850 void dump_callgraph(const char *suffix) {
2851 FILE *F = vcg_open_name("Callgraph", suffix);
2854 int i, rem = edge_label;
2857 dump_vcg_header(F, "Callgraph", NULL);
2859 //colorize = get_irp_callgraph_state() == irp_callgraph_and_calltree_consistent;
2861 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2862 ir_graph *irg = get_irp_irg(i);
2863 ir_entity *ent = get_irg_entity(irg);
2865 //int n_callees = get_irg_n_callees(irg);
2868 //color = colorize ? get_entity_color(ent) : ird_color_green;
2869 color = ird_color_green;
2870 dump_entity_node(F, ent, color);
2871 for (j = 0; j < n_callees; ++j) {
2872 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2873 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2874 int be = is_irg_callee_backedge(irg, j);
2877 "label:\"recursion %d\" color:%d" :
2878 "label:\"calls %d\" color:%d";
2879 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), color);
2888 /* Dump all irgs in interprocedural view to a single file. */
2889 void dump_all_cg_block_graph(const char *suffix) {
2890 FILE *f = vcg_open_name("All_graphs", suffix);
2894 int rem_view = get_interprocedural_view();
2896 set_interprocedural_view(1);
2897 dump_vcg_header(f, "All_graphs", NULL);
2899 /* collect nodes in all irgs reachable in call graph*/
2900 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2901 ird_set_irg_link(get_irp_irg(i), NULL);
2903 cg_walk(clear_link, collect_node, NULL);
2905 /* dump all graphs */
2906 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2907 current_ir_graph = get_irp_irg(i);
2908 assert(ird_get_irg_link(current_ir_graph));
2909 dump_graph_from_list(f, current_ir_graph);
2910 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2914 set_interprocedural_view(rem_view);
2919 /*---------------------------------------------------------------------*/
2920 /* the following routines dumps type information without any ir nodes. */
2921 /*---------------------------------------------------------------------*/
2924 dump_type_graph(ir_graph *irg, const char *suffix)
2928 /* if a filter is set, dump only the irg's that match the filter */
2929 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2931 f = vcg_open(irg, suffix, "-type");
2933 ir_graph *rem = current_ir_graph;
2934 current_ir_graph = irg;
2936 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2938 /* walk over the blocks in the graph */
2939 type_walk_irg(irg, dump_type_info, NULL, f);
2940 /* The walker for the const code can be called several times for the
2941 same (sub) expression. So that no nodes are dumped several times
2942 we decrease the visited flag of the corresponding graph after each
2943 walk. So now increase it finally. */
2944 inc_irg_visited(get_const_code_irg());
2947 current_ir_graph = rem;
2952 dump_all_types(const char *suffix)
2954 FILE *f = vcg_open_name("All_types", suffix);
2956 dump_vcg_header(f, "All_types", NULL);
2957 type_walk(dump_type_info, NULL, f);
2958 inc_irg_visited(get_const_code_irg());
2964 dump_class_hierarchy(int entities, const char *suffix)
2966 FILE *f = vcg_open_name("class_hierarchy", suffix);
2971 env.dump_ent = entities;
2972 dump_vcg_header(f, "class_hierarchy", NULL);
2973 type_walk(dump_class_hierarchy_node, NULL, &env);
2978 /*---------------------------------------------------------------------*/
2979 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2981 /* dump_ir_block_graph */
2983 /* dump_type_graph */
2984 /* dump_ir_graph_w_types */
2985 /*---------------------------------------------------------------------*/
2987 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2989 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2990 dmp_grph(get_irp_irg(i), suffix);
2994 /*--------------------------------------------------------------------------------*
2995 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2996 * packed together in one subgraph/box *
2997 *--------------------------------------------------------------------------------*/
2999 void dump_loops_standalone(FILE *F, ir_loop *loop) {
3000 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
3002 ir_loop *son = NULL;
3004 /* Dump a new loop node. */
3005 dump_loop_node(F, loop);
3007 /* Dump the loop elements. */
3009 for(i = 0; i < get_loop_n_elements(loop); i++) {
3010 le = get_loop_element(loop, i);
3012 if (get_kind(son) == k_ir_loop) {
3014 /* We are a loop son -> Recurse */
3016 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
3017 fprintf(F, "\" }\n");
3018 fprintf(F, "edge: {sourcename: \"");
3020 fprintf(F, "\" targetname: \"");
3022 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3023 loop_node_started = 0;
3025 dump_loop_son_edge(F, loop, son_number++);
3026 dump_loops_standalone(F, son);
3027 } else if (get_kind(son) == k_ir_node) {
3028 /* We are a loop node -> Collect firm nodes */
3030 ir_node *n = le.node;
3033 if (!loop_node_started) {
3034 /* Start a new node which contains all firm nodes of the current loop */
3035 fprintf(F, "node: { title: \"");
3037 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3038 loop_node_started = 1;
3043 bad |= dump_node_label(F, n);
3044 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
3045 if (has_backedges(n)) fprintf(F, "\t loop head!");
3046 } else { /* for callgraph loop tree */
3048 assert(get_kind(son) == k_ir_graph);
3050 /* We are a loop node -> Collect firm graphs */
3051 n = (ir_graph *)le.node;
3052 if (!loop_node_started) {
3053 /* Start a new node which contains all firm nodes of the current loop */
3054 fprintf(F, "node: { title: \"");
3056 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
3057 loop_node_started = 1;
3061 fprintf(F, " %s", get_irg_dump_name(n));
3062 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
3066 if (loop_node_started) {
3067 fprintf(F, "\" }\n");
3068 fprintf(F, "edge: {sourcename: \"");
3070 fprintf(F, "\" targetname: \"");
3072 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
3073 loop_node_started = 0;
3077 void dump_loop_tree(ir_graph *irg, const char *suffix)
3081 /* if a filter is set, dump only the irg's that match the filter */
3082 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
3084 f = vcg_open(irg, suffix, "-looptree");
3086 ir_graph *rem = current_ir_graph;
3087 int el_rem = edge_label;
3089 current_ir_graph = irg;
3092 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
3094 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
3098 edge_label = el_rem;
3099 current_ir_graph = rem;
3103 void dump_callgraph_loop_tree(const char *suffix) {
3105 F = vcg_open_name("Callgraph_looptree", suffix);
3106 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
3107 dump_loops_standalone(F, irp->outermost_cg_loop);
3112 /*----------------------------------------------------------------------------*/
3113 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes.*/
3114 /*----------------------------------------------------------------------------*/
3116 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
3117 int i, son_number = 0, node_number = 0;
3119 if (dump_loop_information_flag) dump_loop_node(F, loop);
3121 for (i = 0; i < get_loop_n_elements(loop); i++) {
3122 loop_element le = get_loop_element(loop, i);
3123 if (*(le.kind) == k_ir_loop) {
3124 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3126 collect_nodeloop(F, le.son, loopnodes);
3128 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3129 eset_insert(loopnodes, le.node);
3134 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
3137 for(i = 0; i < get_loop_n_elements(loop); i++) {
3138 loop_element le = get_loop_element(loop, i);
3139 if (*(le.kind) == k_ir_loop) {
3141 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3143 if (is_Block(le.node)) start = 0; else start = -1;
3144 for (j = start; j < get_irn_arity(le.node); j++) {
3145 ir_node *pred = get_irn_n(le.node, j);
3146 if (!eset_contains(loopnodes, pred)) {
3147 eset_insert(extnodes, pred);
3148 if (!is_Block(pred)) {
3149 pred = get_nodes_block(pred);
3150 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3158 void dump_loop(ir_loop *l, const char *suffix) {
3162 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3163 F = vcg_open_name(name, suffix);
3165 eset *loopnodes = eset_create();
3166 eset *extnodes = eset_create();
3169 dump_vcg_header(F, name, NULL);
3171 /* collect all nodes to dump */
3172 collect_nodeloop(F, l, loopnodes);
3173 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3175 /* build block lists */
3176 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3177 set_irn_link(n, NULL);
3178 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3179 set_irn_link(n, NULL);
3180 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes)) {
3182 b = get_nodes_block(n);
3183 set_irn_link(n, get_irn_link(b));
3187 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes)) {
3189 b = get_nodes_block(n);
3190 set_irn_link(n, get_irn_link(b));
3195 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes)) {
3197 fprintf(F, "graph: { title: \"");
3199 fprintf(F, "\" label: \"");
3200 dump_node_opcode(F, b);
3201 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3202 fprintf(F, "\" status:clustered color:yellow\n");
3204 /* dump the blocks edges */
3205 dump_ir_data_edges(F, b);
3207 /* dump the nodes that go into the block */
3208 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3209 if (eset_contains(extnodes, n))
3210 overrule_nodecolor = ird_color_lightblue;
3212 overrule_nodecolor = ird_color_default;
3213 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3216 /* Close the vcg information for the block */
3218 dump_const_node_local(F, b);
3222 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes)) {
3224 fprintf(F, "graph: { title: \"");
3226 fprintf(F, "\" label: \"");
3227 dump_node_opcode(F, b);
3228 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3229 fprintf(F, "\" status:clustered color:lightblue\n");
3231 /* dump the nodes that go into the block */
3232 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3233 if (!eset_contains(loopnodes, n))
3234 overrule_nodecolor = ird_color_lightblue;
3236 overrule_nodecolor = ird_color_default;
3237 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3240 /* Close the vcg information for the block */
3242 dump_const_node_local(F, b);
3246 eset_destroy(loopnodes);
3247 eset_destroy(extnodes);