3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2006 Universit�t Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
24 #include "firm_common_t.h"
39 #include "type_or_entity.h"
43 #include "callgraph.h"
44 #include "irextbb_t.h"
46 #include "dbginfo_t.h"
58 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
59 extern void dump_irn_state(FILE *FL, ir_node *n);
60 extern int get_opt_dump_abstvals(void);
61 typedef unsigned long SeqNo;
62 extern SeqNo get_Block_seqno(ir_node *n);
65 /* basis for a color range for vcg */
66 static int n_colors = 0;
67 static int base_color = 0;
69 /** Dump only irgs with names that start with this string */
70 static ident *dump_file_filter_id = NULL;
72 #define ERROR_TXT "<ERROR>"
74 /*******************************************************************/
75 /* flags to steer output */
76 /*******************************************************************/
78 /** An option to turn off edge labels */
79 static int edge_label = 1;
80 /** An option to turn off dumping values of constant entities */
81 static int const_entities = 1;
82 /** An option to dump the keep alive edges */
83 static int dump_keepalive = 0;
84 /** An option to dump ld_names instead of names. */
85 static int dump_ld_name = 1;
86 /** Compiler options to dump analysis information in dump_ir_graph */
87 static int dump_out_edge_flag = 0;
88 static int dump_loop_information_flag = 0;
89 static int dump_backedge_information_flag = 1;
90 static int dump_const_local = 0;
91 /** An option to dump all graph anchors */
92 static int dump_anchors = 0;
94 int dump_dominator_information_flag = 0;
95 int opt_dump_analysed_type_info = 1;
96 int opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
98 static dumper_colors overrule_nodecolor = ird_color_default;
100 /** The vcg node attribute hook. */
101 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
102 /** The vcg node attribute hook. */
103 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
104 /** The vcg edge attribute hook. */
105 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
106 /** The vcg dump block edge hook */
107 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
108 /** The vcg dump node edge hook. */
109 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
111 /* Set the hook to be called to dump additional edges to a node. */
112 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func) {
113 dump_node_edge_hook = func;
116 /* Get the additional edge dump hook. */
117 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void) {
118 return dump_node_edge_hook;
121 /* Set the hook to be called to dump additional edges to a block. */
122 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func) {
123 dump_block_edge_hook = func;
126 /* Get the additional block edge dump hook. */
127 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void) {
128 return dump_node_edge_hook;
131 /* set the ir graph hook */
132 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
133 dump_ir_graph_hook = hook;
136 /* set the node attribute hook */
137 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
138 dump_node_vcgattr_hook = hook;
141 /* set the edge attribute hook */
142 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
143 dump_edge_vcgattr_hook = hook;
146 /* Returns 0 if dump_out_edge_flag or dump_loop_information_flag
147 * are set, else returns dump_const_local_flag.
149 int get_opt_dump_const_local(void) {
150 if (!dump_out_edge_flag && !dump_loop_information_flag)
151 return dump_const_local;
156 /* Set a prefix filter for output functions. */
157 void only_dump_method_with_name(ident *name) {
158 dump_file_filter_id = name;
161 /* Returns the prefix filter set with only_dump_method_with_name(). */
162 ident *get_dump_file_filter_ident(void) {
163 return dump_file_filter_id;
166 /* Returns non-zero if dump file filter is not set, or if it is a prefix of name. */
167 int is_filtered_dump_name(ident *name) {
168 if (!dump_file_filter_id) return 1;
169 return id_is_prefix(dump_file_filter_id, name);
172 /* To turn off display of edge labels. Edge labels often cause xvcg to
173 abort with a segmentation fault. */
174 void turn_off_edge_labels(void) {
178 void dump_consts_local(int flag) {
179 dump_const_local = flag;
182 void dump_constant_entity_values(int flag) {
183 const_entities = flag;
186 void dump_keepalive_edges(int flag) {
187 dump_keepalive = flag;
190 int get_opt_dump_keepalive_edges(void) {
191 return dump_keepalive;
194 void dump_out_edges(int flag) {
195 dump_out_edge_flag = flag;
198 void dump_dominator_information(int flag) {
199 dump_dominator_information_flag = flag;
202 void dump_loop_information(int flag) {
203 dump_loop_information_flag = flag;
206 void dump_backedge_information(int flag) {
207 dump_backedge_information_flag = flag;
210 /* Dump the information of type field specified in ana/irtypeinfo.h.
211 * If the flag is set, the type name is output in [] in the node label,
212 * else it is output as info.
214 void set_opt_dump_analysed_type_info(int flag) {
215 opt_dump_analysed_type_info = flag;
218 void dump_pointer_values_to_info(int flag) {
219 opt_dump_pointer_values_to_info = flag;
222 void dump_ld_names(int flag) {
226 void dump_all_anchors(int flag) {
230 /* -------------- some extended helper functions ----------------- */
233 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
234 * in the later case, sets bad
236 const char *get_mode_name_ex(ir_mode *mode, int *bad) {
238 return get_mode_name(mode);
244 * returns the name of a type or <ERROR> if mode is NOT a mode object.
245 * in the later case, sets bad
247 const char *get_type_name_ex(ir_type *tp, int *bad) {
249 return get_type_name(tp);
255 * printf the VCG color to a file
257 static void print_vcg_color(FILE *F, dumper_colors color) {
258 static const char *color_names[32] = {
259 "white", "blue", "red", "green",
260 "yellow", "magenta", "cyan", "darkgray",
261 "darkblue", "darkred", "darkgreen", "darkyellow",
262 "darkmagenta", "darkcyan", "gold", "lightgray",
263 "lightblue", "lightred", "lightgreen", "lightyellow",
264 "lightmagenta", "lightcyan", "lilac", "turquoise",
265 "aquamarine", "khaki", "purple", "yellowgreen",
266 "pink", "orange", "orchid", "black"
269 if (color != ird_color_default)
270 fprintf(F, "color:%s", color_names[color]);
274 * prints the edge from a type S to a type T with additional info fmt, ...
277 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
282 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
283 fprintf(F, " targetname: "); PRINT_TYPEID(T);
284 vfprintf(F, fmt, ap);
290 * prints the edge from a type T to an entity E with additional info fmt, ...
293 static void print_type_ent_edge(FILE *F, ir_type *T, ir_entity *E, const char *fmt, ...)
298 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
299 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
300 vfprintf(F, fmt, ap);
306 * prints the edge from an entity E to an entity T with additional info fmt, ...
309 static void print_ent_ent_edge(FILE *F, ir_entity *E, ir_entity *T, int backedge, const char *fmt, ...)
315 fprintf(F, "backedge: { sourcename: \"");
317 fprintf(F, "edge: { sourcename: \"");
319 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
320 vfprintf(F, fmt, ap);
326 * prints the edge from an entity E to a type T with additional info fmt, ...
329 static void print_ent_type_edge(FILE *F, ir_entity *E, ir_type *T, const char *fmt, ...)
334 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
335 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
336 vfprintf(F, fmt, ap);
342 * prints the edge from a node N to a type T with additional info fmt, ...
345 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
350 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
351 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
352 vfprintf(F, fmt, ap);
358 * prints the edge from a node N to an entity E with additional info fmt, ...
361 static void print_node_ent_edge(FILE *F, const ir_node *N, ir_entity *E, const char *fmt, ...)
366 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
367 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
369 vfprintf(F, fmt, ap);
375 * prints the edge from an entity E to a node N with additional info fmt, ...
378 static void print_ent_node_edge(FILE *F, ir_entity *E, const ir_node *N, const char *fmt, ...)
383 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
384 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
385 vfprintf(F, fmt, ap);
391 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
394 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
399 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
400 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
401 vfprintf(F, fmt, ap);
406 /*-----------------------------------------------------------------*/
407 /* global and ahead declarations */
408 /*-----------------------------------------------------------------*/
410 static void dump_whole_node(ir_node *n, void *env);
411 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
413 /*-----------------------------------------------------------------*/
414 /* Helper functions. */
415 /*-----------------------------------------------------------------*/
418 * This map is used as a private link attr to be able to call dumper
419 * anywhere without destroying link fields.
421 static pmap *irdump_link_map = NULL;
423 /** NOT A STANDARD LIBFIRM INIT METHOD
425 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
426 * are off, we want to have as few interferences as possible. Therefore the
427 * initialization is performed lazily and not called from within init_firm.
429 * Creates the link attribute map. */
430 static void init_irdump(void) {
431 /* We need a new, empty map. */
432 if (irdump_link_map) pmap_destroy(irdump_link_map);
433 irdump_link_map = pmap_create();
434 if (!dump_file_filter_id)
435 dump_file_filter_id = new_id_from_str("");
439 * Returns the private link field.
441 static void *ird_get_irn_link(ir_node *n) {
443 if (!irdump_link_map) return NULL;
445 if (pmap_contains(irdump_link_map, (void *)n))
446 res = pmap_get(irdump_link_map, (void *)n);
451 * Sets the private link field.
453 static void ird_set_irn_link(ir_node *n, void *x) {
454 if (!irdump_link_map)
456 pmap_insert(irdump_link_map, (void *)n, x);
460 * Gets the private link field of an irg.
462 static void *ird_get_irg_link(ir_graph *irg) {
464 if (!irdump_link_map) return NULL;
466 if (pmap_contains(irdump_link_map, (void *)irg))
467 res = pmap_get(irdump_link_map, (void *)irg);
472 * Sets the private link field of an irg.
474 static void ird_set_irg_link(ir_graph *irg, void *x) {
475 if (!irdump_link_map) init_irdump();
476 pmap_insert(irdump_link_map, (void *)irg, x);
480 * Walker, clears the private link field.
482 static void clear_link(ir_node * node, void * env) {
483 ird_set_irn_link(node, NULL);
487 * If the entity has a ld_name, returns it if the dump_ld_name is set,
488 * else returns the name of the entity.
490 static const char *_get_ent_dump_name(ir_entity *ent, int dump_ld_name) {
492 return "<NULL entity>";
494 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
495 if (ent->ld_name) return get_id_str(ent->ld_name);
497 return get_id_str(ent->name);
501 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
502 * else returns the name of the entity.
504 const char *get_ent_dump_name(ir_entity *ent) {
505 return _get_ent_dump_name(ent, dump_ld_name);
508 /* Returns the name of an IRG. */
509 const char *get_irg_dump_name(ir_graph *irg) {
510 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
511 return _get_ent_dump_name(get_irg_entity(irg), 1);
515 * Returns non-zero if a node is in floating state.
517 static int node_floats(ir_node *n) {
518 return ((get_irn_pinned(n) == op_pin_state_floats) &&
519 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
523 * Walker that visits the anchors
525 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
526 irg_walk_graph(irg, pre, post, env);
531 for (i = anchor_max - 1; i >= 0; --i) {
532 ir_node *n = irg->anchors[i];
535 /* reset the visit flag: will be increase in the walker */
536 set_irg_visited(irg, get_irg_visited(irg) - 1);
537 irg_walk(n, pre, post, env);
544 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
546 static void collect_node(ir_node * node, void *env) {
549 || get_irn_op(node) == op_Bad
550 || get_irn_op(node) == op_Unknown
551 || get_irn_op(node) == op_NoMem) {
552 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
553 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
554 ARR_APP1(ir_node *, arr, node);
555 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
557 ir_node * block = get_nodes_block(node);
560 /* this node is in a Bad block, so we must place it into the graph's list */
561 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
562 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
563 ARR_APP1(ir_node *, arr, node);
564 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
566 ird_set_irn_link(node, ird_get_irn_link(block));
567 ird_set_irn_link(block, node);
572 /** Construct lists to walk ir block-wise.
574 * Collects all blocks, nodes not op_pin_state_pinned,
575 * Bad, NoMem and Unknown into a flexible array in link field of
576 * irg they belong to. Sets the irg link field to NULL in all
577 * graphs not visited.
578 * Free the list with DEL_ARR_F().
580 static ir_node **construct_block_lists(ir_graph *irg) {
582 int rem_view = get_interprocedural_view();
583 int walk_flag = using_visited(irg);
584 ir_graph *rem = current_ir_graph;
586 current_ir_graph = irg;
589 clear_using_visited(current_ir_graph);
591 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
592 ird_set_irg_link(get_irp_irg(i), NULL);
594 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
596 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
597 set_interprocedural_view(0);
599 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
600 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
601 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
602 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
604 set_interprocedural_view(rem_view);
607 set_using_visited(current_ir_graph);
609 current_ir_graph = rem;
610 return ird_get_irg_link(irg);
613 typedef struct _list_tuple {
615 ir_extblk **extbb_list;
618 /** Construct lists to walk IR extended block-wise.
619 * Free the lists in the tuple with DEL_ARR_F().
620 * Sets the irg link field to NULL in all
621 * graphs not visited.
623 static list_tuple *construct_extblock_lists(ir_graph *irg) {
624 ir_node **blk_list = construct_block_lists(irg);
626 ir_graph *rem = current_ir_graph;
627 list_tuple *lists = xmalloc(sizeof(*lists));
629 current_ir_graph = irg;
631 lists->blk_list = NEW_ARR_F(ir_node *, 0);
632 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
634 inc_irg_block_visited(irg);
635 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
638 if (is_Block(blk_list[i])) {
639 ext = get_Block_extbb(blk_list[i]);
641 if (extbb_not_visited(ext)) {
642 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
643 mark_extbb_visited(ext);
646 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
650 current_ir_graph = rem;
651 ird_set_irg_link(irg, lists);
655 /*-----------------------------------------------------------------*/
656 /* Routines to dump information about a single ir node. */
657 /*-----------------------------------------------------------------*/
660 * dump the name of a node n to the File F.
662 int dump_node_opcode(FILE *F, ir_node *n)
665 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
667 /* call the dump_node operation if available */
669 return ops->dump_node(n, F, dump_node_opcode_txt);
671 /* implementation for default nodes */
672 switch (get_irn_opcode(n)) {
677 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
678 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
683 switch (get_SymConst_kind(n)) {
684 case symconst_addr_name:
685 /* don't use get_SymConst_ptr_info as it mangles the name. */
686 fprintf(F, "SymC %s", get_id_str(get_SymConst_name(n)));
688 case symconst_addr_ent:
689 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
691 case symconst_ofs_ent:
692 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
694 case symconst_type_tag:
695 fprintf(F, "SymC %s tag", get_type_name_ex(get_SymConst_type(n), &bad));
697 case symconst_type_size:
698 fprintf(F, "SymC %s size", get_type_name_ex(get_SymConst_type(n), &bad));
700 case symconst_type_align:
701 fprintf(F, "SymC %s align", get_type_name_ex(get_SymConst_type(n), &bad));
703 case symconst_enum_const:
704 fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
710 if (!get_interprocedural_view())
717 ir_node *pred = get_Proj_pred(n);
719 if (get_irn_opcode(pred) == iro_Cond
720 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
721 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
722 fprintf(F, "defProj");
730 if (get_interprocedural_view()) {
731 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
736 case iro_CallBegin: {
737 ir_node *addr = get_CallBegin_ptr(n);
738 ir_entity *ent = NULL;
739 if (get_irn_op(addr) == op_Sel)
740 ent = get_Sel_entity(addr);
741 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
742 ent = get_SymConst_entity(addr);
743 fprintf(F, "%s", get_irn_opname(n));
744 if (ent) fprintf(F, " %s", get_entity_name(ent));
748 fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
751 fprintf(F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
754 if (get_Conv_strict(n))
755 fprintf(F, "strict");
756 fprintf(F, "%s", get_irn_opname(n));
761 fprintf(F, "%s", get_irn_opname(n));
768 * Dump the mode of a node n to a file F.
769 * Ignore modes that are "always known".
771 static int dump_node_mode(FILE *F, ir_node *n)
774 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
777 /* call the dump_node operation if available */
779 return ops->dump_node(n, F, dump_node_mode_txt);
781 /* default implementation */
782 iro = get_irn_opcode(n);
794 ir_mode *mode = get_irn_mode(n);
796 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
797 (mode != mode_T || iro == iro_Proj))
798 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
806 * Dump the type of a node n to a file F if it's known.
808 static int dump_node_typeinfo(FILE *F, ir_node *n) {
811 if (opt_dump_analysed_type_info) {
812 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
813 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
814 ir_type *tp = get_irn_typeinfo_type(n);
815 if (tp != firm_none_type)
816 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
824 typedef struct _pns_lookup {
825 long nr; /**< the proj number */
826 const char *name; /**< the name of the Proj */
829 typedef struct _proj_lookup {
830 ir_opcode code; /**< the opcode of the Proj predecessor */
831 unsigned num_data; /**< number of data entries */
832 const pns_lookup_t *data; /**< the data */
835 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
837 /** the lookup table for Proj(Start) names */
838 static const pns_lookup_t start_lut[] = {
839 #define X(a) { pn_Start_##a, #a }
849 /** the lookup table for Proj(Cond) names */
850 static const pns_lookup_t cond_lut[] = {
851 #define X(a) { pn_Cond_##a, #a }
857 /** the lookup table for Proj(Call) names */
858 static const pns_lookup_t call_lut[] = {
859 #define X(a) { pn_Call_##a, #a }
868 /** the lookup table for Proj(Quot) names */
869 static const pns_lookup_t quot_lut[] = {
870 #define X(a) { pn_Quot_##a, #a }
877 /** the lookup table for Proj(DivMod) names */
878 static const pns_lookup_t divmod_lut[] = {
879 #define X(a) { pn_DivMod_##a, #a }
887 /** the lookup table for Proj(Div) names */
888 static const pns_lookup_t div_lut[] = {
889 #define X(a) { pn_Div_##a, #a }
896 /** the lookup table for Proj(Mod) names */
897 static const pns_lookup_t mod_lut[] = {
898 #define X(a) { pn_Mod_##a, #a }
905 /** the lookup table for Proj(Load) names */
906 static const pns_lookup_t load_lut[] = {
907 #define X(a) { pn_Load_##a, #a }
914 /** the lookup table for Proj(Store) names */
915 static const pns_lookup_t store_lut[] = {
916 #define X(a) { pn_Store_##a, #a }
922 /** the lookup table for Proj(Alloc) names */
923 static const pns_lookup_t alloc_lut[] = {
924 #define X(a) { pn_Alloc_##a, #a }
931 /** the lookup table for Proj(CopyB) names */
932 static const pns_lookup_t copyb_lut[] = {
933 #define X(a) { pn_CopyB_##a, #a }
940 /** the lookup table for Proj(InstOf) names */
941 static const pns_lookup_t instof_lut[] = {
942 #define X(a) { pn_InstOf_##a, #a }
950 /** the lookup table for Proj(Raise) names */
951 static const pns_lookup_t raise_lut[] = {
952 #define X(a) { pn_Raise_##a, #a }
958 /** the lookup table for Proj(Bound) names */
959 static const pns_lookup_t bound_lut[] = {
960 #define X(a) { pn_Bound_##a, #a }
967 /** the Proj lookup table */
968 static const proj_lookup_t proj_lut[] = {
969 #define E(a) ARR_SIZE(a), a
970 { iro_Start, E(start_lut) },
971 { iro_Cond, E(cond_lut) },
972 { iro_Call, E(call_lut) },
973 { iro_Quot, E(quot_lut) },
974 { iro_DivMod, E(divmod_lut) },
975 { iro_Div, E(div_lut) },
976 { iro_Mod, E(mod_lut) },
977 { iro_Load, E(load_lut) },
978 { iro_Store, E(store_lut) },
979 { iro_Alloc, E(alloc_lut) },
980 { iro_CopyB, E(copyb_lut) },
981 { iro_InstOf, E(instof_lut) },
982 { iro_Raise, E(raise_lut) },
983 { iro_Bound, E(bound_lut) }
988 * Dump additional node attributes of some nodes to a file F.
991 dump_node_nodeattr(FILE *F, ir_node *n)
997 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
999 /* call the dump_node operation if available */
1001 return ops->dump_node(n, F, dump_node_nodeattr_txt);
1003 switch (get_irn_opcode(n)) {
1005 if (0 && get_interprocedural_view()) {
1006 fprintf(F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
1011 pred = get_Proj_pred(n);
1012 proj_nr = get_Proj_proj(n);
1014 code = get_irn_opcode(pred);
1016 if (code == iro_Cmp)
1017 fprintf(F, "%s ", get_pnc_string(get_Proj_proj(n)));
1018 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1019 fprintf(F, "Arg %ld ", proj_nr);
1020 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1021 fprintf(F, "%ld ", proj_nr);
1023 unsigned i, j, f = 0;
1025 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
1026 if (code == proj_lut[i].code) {
1027 for (j = 0; j < proj_lut[i].num_data; ++j) {
1028 if (proj_nr == proj_lut[i].data[j].nr) {
1029 fprintf(F, "%s ", proj_lut[i].data[j].name);
1038 fprintf(F, "%ld ", proj_nr);
1039 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1040 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1041 fprintf(F, "PRED ");
1042 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1043 fprintf(F, "PRED ");
1048 proj_nr = get_Filter_proj(n);
1049 if (! get_interprocedural_view()) {
1051 pred = get_Filter_pred(n);
1054 fprintf(F, "%ld ", proj_nr);
1057 fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1060 fprintf(F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1063 fprintf(F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1066 fprintf(F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1077 #include "execution_frequency.h"
1079 static void dump_node_ana_vals(FILE *F, ir_node *n) {
1081 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1082 get_irn_exec_freq(n),
1083 get_irg_method_execution_frequency(get_irn_irg(n)),
1084 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1085 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1090 /* Dumps a node label without the enclosing ". */
1091 int dump_node_label(FILE *F, ir_node *n) {
1094 bad |= dump_node_opcode(F, n);
1095 bad |= dump_node_mode(F, n);
1097 bad |= dump_node_typeinfo(F, n);
1098 bad |= dump_node_nodeattr(F, n);
1099 fprintf(F, "%ld:%d", get_irn_node_nr(n), get_irn_idx(n));
1106 * Dumps the attributes of a node n into the file F.
1107 * Currently this is only the color of a node.
1109 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1114 print_vcg_color(F, ird_color_red);
1118 if (dump_node_vcgattr_hook)
1119 if (dump_node_vcgattr_hook(F, node, local))
1122 n = local ? local : node;
1124 if (overrule_nodecolor != ird_color_default) {
1125 print_vcg_color(F, overrule_nodecolor);
1129 switch (get_irn_opcode(n)) {
1136 print_vcg_color(F, ird_color_blue);
1139 if (is_Block_dead(n))
1140 print_vcg_color(F, ird_color_lightred);
1142 print_vcg_color(F, ird_color_lightyellow);
1145 print_vcg_color(F, ird_color_green);
1149 print_vcg_color(F, ird_color_gold);
1152 print_vcg_color(F, ird_color_orchid);
1158 print_vcg_color(F, ird_color_yellow);
1161 PRINT_DEFAULT_NODE_ATTR;
1165 /* Adds a new node info dumper callback. */
1166 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1168 hook_entry_t *info = xmalloc(sizeof(*info));
1170 info->hook._hook_node_info = cb;
1171 info->context = data;
1172 register_hook(hook_node_info, info);
1177 /* Remove a previously added info dumper callback. */
1178 void dump_remv_node_info_callback(void *handle)
1180 hook_entry_t *info = handle;
1181 unregister_hook(hook_node_info, info);
1186 * Dump the node information of a node n to a file F.
1188 static INLINE int dump_node_info(FILE *F, ir_node *n)
1191 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1193 fprintf(F, " info1: \"");
1194 bad = dump_irnode_to_file(F, n);
1195 /* call the dump_node operation if available */
1197 bad = ops->dump_node(n, F, dump_node_info_txt);
1199 /* allow additional info to be added */
1200 hook_node_info(F, n);
1207 * checks whether a node is "constant-like" ie can be treated "block-less"
1210 int is_constlike_node(ir_node *n) {
1211 ir_opcode code = get_irn_opcode(n);
1212 return (code == iro_Const || code == iro_Bad || code == iro_NoMem || code == iro_SymConst || code == iro_Unknown);
1216 /** outputs the predecessors of n, that are constants, local. I.e.,
1217 generates a copy of the constant predecessors for each node called with. */
1218 static void dump_const_node_local(FILE *F, ir_node *n) {
1220 if (!get_opt_dump_const_local()) return;
1222 /* Use visited flag to avoid outputting nodes twice.
1223 initialize it first. */
1224 for (i = 0; i < get_irn_arity(n); i++) {
1225 ir_node *con = get_irn_n(n, i);
1226 if (is_constlike_node(con)) {
1227 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1231 for (i = 0; i < get_irn_arity(n); i++) {
1232 ir_node *con = get_irn_n(n, i);
1233 if (is_constlike_node(con) && irn_not_visited(con)) {
1236 mark_irn_visited(con);
1237 /* Generate a new name for the node by appending the names of
1239 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1240 fprintf(F, " label: \"");
1241 bad |= dump_node_label(F, con);
1243 bad |= dump_node_info(F, con);
1244 dump_node_vcgattr(F, n, con, bad);
1250 /** If the block of an edge is a const_like node, dump it local with an edge */
1251 static void dump_const_block_local(FILE *F, ir_node *n) {
1254 if (!get_opt_dump_const_local()) return;
1256 blk = get_nodes_block(n);
1257 if (is_constlike_node(blk)) {
1260 /* Generate a new name for the node by appending the names of
1262 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1263 fprintf(F, "\" label: \"");
1264 bad |= dump_node_label(F, blk);
1266 bad |= dump_node_info(F, blk);
1267 dump_node_vcgattr(F, n, blk, bad);
1270 fprintf(F, "edge: { sourcename: \"");
1272 fprintf(F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1274 if (dump_edge_vcgattr_hook) {
1276 if (dump_edge_vcgattr_hook(F, n, -1)) {
1280 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1285 fprintf(F, "\" " BLOCK_EDGE_ATTR "}\n");
1290 * prints the error message of a node to a file F as info2.
1292 static void print_node_error(FILE *F, const char *err_msg)
1297 fprintf(F, " info2: \"%s\"", err_msg);
1301 * prints debug messages of a node to file F as info3.
1303 static void print_dbg_info(FILE *F, dbg_info *dbg)
1307 if (__dbg_info_snprint) {
1309 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1310 fprintf(F, " info3: \"%s\"\n", buf);
1317 static void dump_node(FILE *F, ir_node *n)
1322 if (get_opt_dump_const_local() && is_constlike_node(n))
1325 /* dump this node */
1326 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1328 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1329 bad |= dump_node_label(F, n);
1330 dump_node_ana_vals(F, n);
1331 //dump_node_ana_info(F, n);
1333 bad |= dump_node_info(F, n);
1334 print_node_error(F, p);
1335 print_dbg_info(F, get_irn_dbg_info(n));
1336 dump_node_vcgattr(F, n, NULL, bad);
1338 dump_const_node_local(F, n);
1340 if(dump_node_edge_hook)
1341 dump_node_edge_hook(F, n);
1343 dump_irn_chi_term(F, n);
1344 dump_irn_state(F, n);
1348 /** dump the edge to the block this node belongs to */
1350 dump_ir_block_edge(FILE *F, ir_node *n) {
1351 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1352 if (is_no_Block(n)) {
1353 ir_node *block = get_nodes_block(n);
1355 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1356 dump_const_block_local(F, n);
1358 fprintf(F, "edge: { sourcename: \"");
1360 fprintf(F, "\" targetname: ");
1361 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1363 if (dump_edge_vcgattr_hook) {
1365 if (dump_edge_vcgattr_hook(F, n, -1)) {
1369 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1374 fprintf(F, " " BLOCK_EDGE_ATTR "}\n");
1380 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1382 * do not use get_nodes_block() here, will fail
1383 * if the irg is not pinned.
1385 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1386 fprintf(F, INTRA_DATA_EDGE_ATTR);
1388 fprintf(F, INTER_DATA_EDGE_ATTR);
1392 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1394 * do not use get_nodes_block() here, will fail
1395 * if the irg is not pinned.
1397 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1398 fprintf(F, INTRA_MEM_EDGE_ATTR);
1400 fprintf(F, INTER_MEM_EDGE_ATTR);
1404 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1407 if (dump_edge_vcgattr_hook)
1408 if (dump_edge_vcgattr_hook(F, from, to))
1411 if (dump_backedge_information_flag && is_backedge(from, to))
1412 fprintf(F, BACK_EDGE_ATTR);
1414 switch (get_irn_opcode(from)) {
1416 fprintf(F, CF_EDGE_ATTR);
1418 case iro_Start: break;
1421 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1422 fprintf(F, CF_EDGE_ATTR);
1423 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1424 fprintf(F, INTER_MEM_EDGE_ATTR);
1428 if (is_Proj(from)) {
1429 if (get_irn_mode(from) == mode_M)
1430 print_mem_edge_vcgattr(F, from, to);
1431 else if (get_irn_mode(from) == mode_X)
1432 fprintf(F, CF_EDGE_ATTR);
1434 print_data_edge_vcgattr(F, from, to);
1436 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1437 print_mem_edge_vcgattr(F, from, to);
1438 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1439 fprintf(F, CF_EDGE_ATTR);
1441 print_data_edge_vcgattr(F, from, to);
1445 /* dump edges to our inputs */
1447 dump_ir_data_edges(FILE *F, ir_node *n) {
1449 unsigned long visited = get_irn_visited(n);
1451 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1454 /* dump the dependency edges. */
1455 for (i = 0; i < get_irn_deps(n); ++i) {
1456 ir_node *dep = get_irn_dep(n, i);
1459 fprintf(F, "edge: {sourcename: \"");
1461 fprintf(F, "\" targetname: ");
1462 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1463 PRINT_CONSTID(n, dep);
1469 fprintf(F, " label: \"%d\" ", i);
1470 fprintf(F, " color: darkgreen}\n");
1474 for (i = 0; i < get_irn_arity(n); i++) {
1475 ir_node * pred = get_irn_n(n, i);
1478 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1479 continue; /* pred not dumped */
1481 if (dump_backedge_information_flag && is_backedge(n, i))
1482 fprintf(F, "backedge: {sourcename: \"");
1484 fprintf(F, "edge: {sourcename: \"");
1486 fprintf(F, "\" targetname: ");
1487 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1488 PRINT_CONSTID(n, pred);
1490 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1492 fprintf(F, " label: \"%d\" ", i);
1493 print_edge_vcgattr(F, n, i);
1498 /** Dumps a node and its edges but not the block edge
1501 dump_node_wo_blockedge(ir_node *n, void *env) {
1504 dump_ir_data_edges(F, n);
1507 /** Dumps a node and its edges.
1510 dump_whole_node(ir_node *n, void *env) {
1512 dump_node_wo_blockedge(n, env);
1513 if (!node_floats(n)) dump_ir_block_edge(F, n);
1517 dump_const_node(ir_node *n, void *env) {
1518 if (is_Block(n)) return;
1519 dump_node_wo_blockedge(n, env);
1522 /***********************************************************************/
1523 /* the following routines dump the nodes/irgs bracketed to graphs. */
1524 /***********************************************************************/
1526 /** Dumps a constant expression as entity initializer, array bound ...
1528 static void dump_const_expression(FILE *F, ir_node *value) {
1529 ir_graph *rem = current_ir_graph;
1530 int rem_dump_const_local = dump_const_local;
1531 dump_const_local = 0;
1532 current_ir_graph = get_const_code_irg();
1533 irg_walk(value, dump_const_node, NULL, F);
1534 /* Decrease visited flag so that we walk with the same flag for the next
1535 expression. This guarantees that we don't dump the same node twice,
1536 as for const expressions cse is performed to save memory. */
1537 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1538 current_ir_graph = rem;
1539 dump_const_local = rem_dump_const_local;
1542 /** Dump a block as graph containing its nodes.
1544 * Expects to find nodes belonging to the block as list in its
1546 * Dumps the edges of all nodes including itself. */
1548 dump_whole_block(FILE *F, ir_node *block) {
1550 dumper_colors color = ird_color_yellow;
1552 assert(is_Block(block));
1554 fprintf(F, "graph: { title: \"");
1555 PRINT_NODEID(block);
1556 fprintf(F, "\" label: \"");
1557 dump_node_label(F, block);
1559 if (get_opt_dump_abstvals())
1560 fprintf(F, " seqno: %d", (int)get_Block_seqno(block));
1563 /* colorize blocks */
1564 if (! get_Block_matured(block))
1565 color = ird_color_red;
1566 if (is_Block_dead(block))
1567 color = ird_color_orange;
1569 fprintf(F, "\" status:clustered ");
1570 print_vcg_color(F, color);
1573 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1574 dump_node_info(F, block);
1575 print_dbg_info(F, get_irn_dbg_info(block));
1577 /* dump the blocks edges */
1578 dump_ir_data_edges(F, block);
1580 if (dump_block_edge_hook)
1581 dump_block_edge_hook(F, block);
1583 /* dump the nodes that go into the block */
1584 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1586 dump_ir_data_edges(F, node);
1589 /* Close the vcg information for the block */
1591 dump_const_node_local(F, block);
1593 dump_irn_chi_term(F, block);
1598 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1599 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1601 dump_block_graph(FILE *F, ir_graph *irg) {
1603 ir_graph *rem = current_ir_graph;
1604 ir_node **arr = ird_get_irg_link(irg);
1605 current_ir_graph = irg;
1607 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1608 ir_node * node = arr[i];
1609 if (is_Block(node)) {
1610 /* Dumps the block and all the nodes in the block, which are to
1611 be found in Block->link. */
1612 dump_whole_block(F, node);
1614 /* Nodes that are not in a Block. */
1616 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1617 dump_const_block_local(F, node);
1619 dump_ir_data_edges(F, node);
1623 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1624 dump_loop_nodes_into_graph(F, irg);
1626 current_ir_graph = rem;
1630 * Dump the info for an irg.
1631 * Parsed by XVCG but not shown. use yComp.
1633 static void dump_graph_info(FILE *F, ir_graph *irg) {
1634 fprintf(F, "info1: \"");
1635 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1639 /** Dumps an irg as a graph clustered by block nodes.
1640 * If interprocedural view edges can point to nodes out of this graph.
1642 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1643 ir_entity *ent = get_irg_entity(irg);
1645 fprintf(F, "graph: { title: \"");
1647 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1648 get_ent_dump_name(ent));
1650 dump_graph_info(F, irg);
1651 print_dbg_info(F, get_entity_dbg_info(ent));
1653 dump_block_graph(F, irg);
1655 /* Close the vcg information for the irg */
1656 fprintf(F, "}\n\n");
1659 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1660 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1662 dump_extblock_graph(FILE *F, ir_graph *irg) {
1664 ir_graph *rem = current_ir_graph;
1665 ir_extblk **arr = ird_get_irg_link(irg);
1666 current_ir_graph = irg;
1668 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1669 ir_extblk *extbb = arr[i];
1670 ir_node *leader = get_extbb_leader(extbb);
1673 fprintf(F, "graph: { title: \"");
1674 PRINT_EXTBBID(leader);
1675 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1676 get_irn_node_nr(leader));
1678 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1679 ir_node * node = extbb->blks[j];
1680 if (is_Block(node)) {
1681 /* Dumps the block and all the nodes in the block, which are to
1682 be found in Block->link. */
1683 dump_whole_block(F, node);
1685 /* Nodes that are not in a Block. */
1687 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1688 dump_const_block_local(F, node);
1690 dump_ir_data_edges(F, node);
1696 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1697 dump_loop_nodes_into_graph(F, irg);
1699 current_ir_graph = rem;
1704 /*******************************************************************/
1705 /* Basic type and entity nodes and edges. */
1706 /*******************************************************************/
1708 /** dumps the edges between nodes and their type or entity attributes. */
1709 static void dump_node2type_edges(ir_node *n, void *env)
1714 switch (get_irn_opcode(n)) {
1716 /* @@@ some consts have an entity */
1719 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1720 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1723 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1726 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1729 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1732 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1735 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1743 static int print_type_info(FILE *F, ir_type *tp) {
1746 if (get_type_state(tp) == layout_undefined) {
1747 fprintf(F, "state: layout_undefined\n");
1749 fprintf(F, "state: layout_fixed,\n");
1751 if (get_type_mode(tp))
1752 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1753 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1758 static void print_typespecific_info(FILE *F, ir_type *tp) {
1759 switch (get_type_tpop_code(tp)) {
1761 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1766 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1767 fprintf(F, "params: %d\n", get_method_n_params(tp));
1768 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1774 case tpo_enumeration:
1786 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1787 switch (get_type_tpop_code(tp)) {
1789 if (peculiarity_existent == get_class_peculiarity(tp))
1790 fprintf(F, " " TYPE_CLASS_NODE_ATTR);
1792 fprintf(F, " " TYPE_DESCRIPTION_NODE_ATTR);
1795 fprintf(F, " " TYPE_METH_NODE_ATTR);
1803 case tpo_enumeration:
1815 int dump_type_node(FILE *F, ir_type *tp)
1819 fprintf(F, "node: {title: ");
1821 fprintf(F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1822 fprintf(F, " info1: \"");
1824 bad |= print_type_info(F, tp);
1825 print_typespecific_info(F, tp);
1827 dump_type_to_file(F, tp, dump_verbosity_max);
1830 print_dbg_info(F, get_type_dbg_info(tp));
1831 print_typespecific_vcgattr(F, tp);
1838 void dump_entity_node(FILE *F, ir_entity *ent, int color)
1840 fprintf(F, "node: {title: \"");
1841 PRINT_ENTID(ent); fprintf(F, "\"");
1842 fprintf(F, DEFAULT_TYPE_ATTRIBUTE);
1843 fprintf(F, "label: ");
1844 fprintf(F, "\"ent %s\" ", get_ent_dump_name(ent));
1846 fprintf(F, "color:%d", color);
1848 fprintf(F, ENTITY_NODE_ATTR);
1849 fprintf(F, "\n info1: \"");
1851 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1854 print_dbg_info(F, get_entity_dbg_info(ent));
1858 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1861 ir_enum_const *ec = get_enumeration_const(tp, pos);
1862 ident *id = get_enumeration_nameid(ec);
1863 tarval *tv = get_enumeration_value(ec);
1866 tarval_snprintf(buf, sizeof(buf), tv);
1868 strncpy(buf, "<not set>", sizeof(buf));
1869 fprintf(F, "node: {title: \"");
1870 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1871 fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1872 fprintf(F, "label: ");
1873 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1874 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1877 /* dumps a type or entity and it's edges. */
1879 dump_type_info(type_or_ent *tore, void *env) {
1881 int i = 0; /* to shutup gcc */
1883 /* dump this type or entity */
1885 switch (get_kind(tore)) {
1887 ir_entity *ent = (ir_entity *)tore;
1890 dump_entity_node(F, ent, 0);
1892 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1893 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1894 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1895 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1896 if (is_Class_type(get_entity_owner(ent))) {
1897 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1898 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1900 /* attached subgraphs */
1901 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1902 if (is_atomic_entity(ent)) {
1903 value = get_atomic_ent_value(ent);
1905 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1906 /* DDMN(value); $$$ */
1907 dump_const_expression(F, value);
1910 if (is_compound_entity(ent)) {
1911 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1912 value = get_compound_ent_value(ent, i);
1914 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1915 dump_const_expression(F, value);
1916 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1918 fprintf(F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1919 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1920 get_compound_ent_value_member(ent, i), i);
1929 ir_type *tp = (ir_type *)tore;
1930 dump_type_node(F, tp);
1931 /* and now the edges */
1932 switch (get_type_tpop_code(tp)) {
1934 for (i=0; i < get_class_n_supertypes(tp); i++)
1935 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1936 for (i=0; i < get_class_n_members(tp); i++)
1937 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1940 for (i=0; i < get_struct_n_members(tp); i++)
1941 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1944 for (i = 0; i < get_method_n_params(tp); i++)
1945 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1946 for (i = 0; i < get_method_n_ress(tp); i++)
1947 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1950 for (i = 0; i < get_union_n_members(tp); i++)
1951 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1954 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1955 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1956 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1957 ir_node *upper = get_array_upper_bound(tp, i);
1958 ir_node *lower = get_array_lower_bound(tp, i);
1959 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1960 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1961 dump_const_expression(F, upper);
1962 dump_const_expression(F, lower);
1965 case tpo_enumeration:
1966 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1967 dump_enum_item(F, tp, i);
1968 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1972 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1979 break; /* case k_type */
1982 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1983 } /* switch kind_or_entity */
1986 typedef struct _h_env {
1991 /** For dumping class hierarchies.
1992 * Dumps a class type node and a superclass edge.
1993 * If env->dump_ent dumps entities of classes and overwrites edges.
1996 dump_class_hierarchy_node(type_or_ent *tore, void *ctx) {
1999 int i = 0; /* to shutup gcc */
2001 /* dump this type or entity */
2002 switch (get_kind(tore)) {
2004 ir_entity *ent = (ir_entity *)tore;
2005 if (get_entity_owner(ent) == get_glob_type()) break;
2006 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
2007 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2009 dump_entity_node(F, ent, 0);
2011 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
2012 for(i = 0; i < get_entity_n_overwrites(ent); i++)
2013 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
2018 ir_type *tp = (ir_type *)tore;
2019 if (tp == get_glob_type()) break;
2020 switch (get_type_tpop_code(tp)) {
2022 dump_type_node(F, tp);
2023 /* and now the edges */
2024 for (i=0; i < get_class_n_supertypes(tp); i++) {
2025 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2030 break; /* case k_type */
2033 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2034 } /* switch kind_or_entity */
2037 /*******************************************************************/
2038 /* dump analysis information that is expressed in graph terms. */
2039 /*******************************************************************/
2041 /* dump out edges */
2043 dump_out_edge(ir_node *n, void *env) {
2046 for (i = 0; i < get_irn_n_outs(n); i++) {
2047 assert(get_irn_out(n, i));
2048 fprintf(F, "edge: {sourcename: \"");
2050 fprintf(F, "\" targetname: \"");
2051 PRINT_NODEID(get_irn_out(n, i));
2052 fprintf(F, "\" color: red linestyle: dashed");
2058 dump_loop_label(FILE *F, ir_loop *loop) {
2059 fprintf(F, "loop %d, %d sons, %d nodes",
2060 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2063 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2064 fprintf(F, " info1: \"");
2065 fprintf(F, " loop nr: %d", get_loop_loop_nr(loop));
2066 #ifdef DEBUG_libfirm /* GL @@@ debug analyses */
2067 fprintf(F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2073 dump_loop_node(FILE *F, ir_loop *loop) {
2074 fprintf(F, "node: {title: \"");
2076 fprintf(F, "\" label: \"");
2077 dump_loop_label(F, loop);
2079 dump_loop_info(F, loop);
2084 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2086 fprintf(F, "edge: {sourcename: \"");
2088 fprintf(F, "\" targetname: \"");
2089 PRINT_NODEID(get_loop_node(loop, i));
2090 fprintf(F, "\" color: green");
2095 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2097 fprintf(F, "edge: {sourcename: \"");
2099 fprintf(F, "\" targetname: \"");
2100 PRINT_LOOPID(get_loop_son(loop, i));
2101 fprintf(F, "\" color: darkgreen label: \"%d\"}\n",
2102 get_loop_element_pos(loop, get_loop_son(loop, i)));
2106 void dump_loops(FILE *F, ir_loop *loop) {
2108 /* dump this loop node */
2109 dump_loop_node(F, loop);
2111 /* dump edges to nodes in loop -- only if it is a real loop */
2112 if (get_loop_depth(loop) != 0) {
2113 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2114 dump_loop_node_edge(F, loop, i);
2117 for (i = 0; i < get_loop_n_sons(loop); i++) {
2118 dump_loops(F, get_loop_son(loop, i));
2119 dump_loop_son_edge(F, loop, i);
2124 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2125 ir_graph *rem = current_ir_graph;
2126 current_ir_graph = irg;
2128 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2130 current_ir_graph = rem;
2135 * dumps the VCG header
2137 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2146 if (!orientation) orientation = "bottom_to_top";
2150 "graph: { title: \"ir graph of %s\"\n"
2151 "display_edge_labels: %s\n"
2152 "layoutalgorithm: mindepth\n"
2153 "manhattan_edges: yes\n"
2154 "port_sharing: no\n"
2156 "classname 1: \"intrablock Data\"\n"
2157 "classname 2: \"Block\"\n"
2158 "classname 3: \"Entity type\"\n"
2159 "classname 4: \"Entity owner\"\n"
2160 "classname 5: \"Method Param\"\n"
2161 "classname 6: \"Method Res\"\n"
2162 "classname 7: \"Super\"\n"
2163 "classname 8: \"Union\"\n"
2164 "classname 9: \"Points-to\"\n"
2165 "classname 10: \"Array Element Type\"\n"
2166 "classname 11: \"Overwrites\"\n"
2167 "classname 12: \"Member\"\n"
2168 "classname 13: \"Control Flow\"\n"
2169 "classname 14: \"intrablock Memory\"\n"
2170 "classname 15: \"Dominators\"\n"
2171 "classname 16: \"interblock Data\"\n"
2172 "classname 17: \"interblock Memory\"\n"
2173 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2174 "classname 19: \"Postdominators\"\n"
2175 "infoname 1: \"Attribute\"\n"
2176 "infoname 2: \"Verification errors\"\n"
2177 "infoname 3: \"Debug info\"\n",
2178 name, label, orientation);
2180 /* don't use all, the range is too whith/black. */
2184 "colorentry 100: 0 0 0\n"
2185 "colorentry 101: 20 0 0\n"
2186 "colorentry 102: 40 0 0\n"
2187 "colorentry 103: 60 0 0\n"
2188 "colorentry 104: 80 0 0\n"
2189 "colorentry 105: 100 0 0\n"
2190 "colorentry 106: 120 0 0\n"
2191 "colorentry 107: 140 0 0\n"
2192 "colorentry 108: 150 0 0\n"
2193 "colorentry 109: 180 0 0\n"
2194 "colorentry 110: 200 0 0\n"
2195 "colorentry 111: 220 0 0\n"
2196 "colorentry 112: 240 0 0\n"
2197 "colorentry 113: 255 0 0\n"
2198 "colorentry 113: 255 20 20\n"
2199 "colorentry 114: 255 40 40\n"
2200 "colorentry 115: 255 60 60\n"
2201 "colorentry 116: 255 80 80\n"
2202 "colorentry 117: 255 100 100\n"
2203 "colorentry 118: 255 120 120\n"
2204 "colorentry 119: 255 140 140\n"
2205 "colorentry 120: 255 150 150\n"
2206 "colorentry 121: 255 180 180\n"
2207 "colorentry 122: 255 200 200\n"
2208 "colorentry 123: 255 220 220\n"
2209 "colorentry 124: 255 240 240\n"
2210 "colorentry 125: 255 250 250\n"
2213 fprintf(F, "\n"); /* a separator */
2219 * @param irg The graph to be dumped
2220 * @param suffix1 first filename suffix
2221 * @param suffix2 second filename suffix
2223 FILE *vcg_open(ir_graph *irg, const char * suffix1, const char *suffix2) {
2225 const char *nm = get_irg_dump_name(irg);
2226 int len = strlen(nm), i, j;
2227 char *fname; /* filename to put the vcg information in */
2229 if (!suffix1) suffix1 = "";
2230 if (!suffix2) suffix2 = "";
2232 /* open file for vcg graph */
2233 fname = xmalloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2235 /* strncpy (fname, nm, len); */ /* copy the filename */
2237 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2239 fname[j] = '@'; j++; fname[j] = '1'; j++;
2240 } else if (nm[i] == '@') {
2241 fname[j] = '@'; j++; fname[j] = '2'; j++;
2243 fname[j] = nm[i]; j++;
2247 strcat(fname, suffix1); /* append file suffix */
2248 strcat(fname, suffix2); /* append file suffix */
2249 strcat(fname, ".vcg"); /* append the .vcg suffix */
2251 /* vcg really expect only a <CR> at end of line, so
2252 * the "b"inary mode is what you mean (and even needed for Win32)
2254 F = fopen(fname, "wb"); /* open file for writing */
2266 * @param name prefix file name
2267 * @param suffix filename suffix
2269 FILE *vcg_open_name(const char *name, const char *suffix) {
2271 char *fname; /* filename to put the vcg information in */
2272 int i, j, len = strlen(name);
2274 if (!suffix) suffix = "";
2276 /** open file for vcg graph */
2277 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2278 /* strcpy (fname, name);*/ /* copy the filename */
2280 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2281 if (name[i] == '/') {
2282 fname[j] = '@'; j++; fname[j] = '1'; j++;
2283 } else if (name[i] == '@') {
2284 fname[j] = '@'; j++; fname[j] = '2'; j++;
2286 fname[j] = name[i]; j++;
2290 strcat(fname, suffix);
2291 strcat(fname, ".vcg"); /* append the .vcg suffix */
2293 /* vcg really expect only a <CR> at end of line, so
2294 * the "b"inary mode is what you mean (and even needed for Win32)
2296 F = fopen(fname, "wb"); /* open file for writing */
2306 * Dumps the vcg file footer
2308 static void dump_vcg_footer(FILE *F) {
2313 * close the vcg file
2315 void vcg_close(FILE *F) {
2316 dump_vcg_footer(F); /* print footer */
2317 fclose (F); /* close vcg file */
2320 /************************************************************************/
2321 /************************************************************************/
2322 /* Routines that dump all or parts of the firm representation to a file */
2323 /************************************************************************/
2324 /************************************************************************/
2326 /************************************************************************/
2327 /* Dump ir graphs, different formats and additional information. */
2328 /************************************************************************/
2330 /** Routine to dump a graph, blocks as conventional nodes. */
2332 dump_ir_graph(ir_graph *irg, const char *suffix )
2338 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2341 if (dump_backedge_information_flag && get_irg_loopinfo_state(irg) != loopinfo_consistent) {
2342 construct_backedges(irg);
2345 rem = current_ir_graph;
2346 current_ir_graph = irg;
2347 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2348 else suffix1 = "-pure";
2349 f = vcg_open(irg, suffix, suffix1);
2351 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2353 /* call the dump graph hook */
2354 if (dump_ir_graph_hook)
2355 if (dump_ir_graph_hook(f, irg)) {
2356 current_ir_graph = rem;
2360 /* walk over the graph */
2361 /* dump_whole_node must be called in post visiting predecessors */
2362 ird_walk_graph(irg, NULL, dump_whole_node, f);
2364 /* dump the out edges in a separate walk */
2365 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2366 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2371 current_ir_graph = rem;
2374 /* Dump a firm graph without explicit block nodes. */
2375 void dump_ir_block_graph(ir_graph *irg, const char *suffix)
2381 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2384 if (get_interprocedural_view()) suffix1 = "-ip";
2386 f = vcg_open(irg, suffix, suffix1);
2389 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2391 construct_block_lists(irg);
2394 * If we are in the interprocedural view, we dump not
2395 * only the requested irg but also all irgs that can be reached
2398 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2399 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2401 dump_graph_from_list(f, get_irp_irg(i));
2410 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2411 void dump_ir_extblock_graph(ir_graph *irg, const char *suffix)
2418 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2421 if (get_irg_extblk_state(irg) != extblk_valid)
2424 if (get_interprocedural_view()) suffix1 = "-ip";
2427 ent = get_irg_entity(irg);
2429 F = vcg_open(irg, suffix, suffix1);
2431 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2433 construct_extblock_lists(irg);
2435 fprintf(F, "graph: { title: \"");
2437 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2438 get_ent_dump_name(ent));
2440 dump_graph_info(F, irg);
2441 print_dbg_info(F, get_entity_dbg_info(ent));
2443 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2444 ir_graph *irg = get_irp_irg(i);
2445 list_tuple *lists = ird_get_irg_link(irg);
2448 /* dump the extended blocks first */
2449 if (ARR_LEN(lists->extbb_list)) {
2450 ird_set_irg_link(irg, lists->extbb_list);
2451 dump_extblock_graph(F, irg);
2454 /* we may have blocks without extended blocks, bad for instance */
2455 if (ARR_LEN(lists->blk_list)) {
2456 ird_set_irg_link(irg, lists->blk_list);
2457 dump_block_graph(F, irg);
2460 DEL_ARR_F(lists->extbb_list);
2461 DEL_ARR_F(lists->blk_list);
2466 /* Close the vcg information for the irg */
2467 fprintf(F, "}\n\n");
2474 /* dumps a graph with type information */
2476 dump_ir_graph_w_types(ir_graph *irg, const char *suffix)
2481 /* if a filter is set, dump only the irg's that match the filter */
2482 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2485 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2486 else suffix1 = "-pure-wtypes";
2487 f = vcg_open(irg,suffix, suffix1);
2489 ir_graph *rem = current_ir_graph;
2490 int rem_dump_const_local;
2492 current_ir_graph = irg;
2493 rem_dump_const_local = dump_const_local;
2494 /* dumping types does not work with local nodes */
2495 dump_const_local = 0;
2497 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2499 /* dump common ir graph */
2500 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2501 /* dump type info */
2502 type_walk_irg(irg, dump_type_info, NULL, f);
2503 inc_irg_visited(get_const_code_irg());
2504 /* dump edges from graph to type info */
2505 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2508 dump_const_local = rem_dump_const_local;
2509 current_ir_graph = rem;
2514 dump_ir_block_graph_w_types(ir_graph *irg, const char *suffix)
2520 /* if a filter is set, dump only the irg's that match the filter */
2521 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2524 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2525 else suffix1 = "-wtypes";
2526 f = vcg_open(irg, suffix, suffix1);
2528 ir_graph *rem = current_ir_graph;
2529 int rem_dump_const_local;
2531 rem_dump_const_local = dump_const_local;
2532 /* dumping types does not work with local nodes */
2533 dump_const_local = 0;
2535 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2537 /* dump common blocked ir graph */
2538 construct_block_lists(irg);
2540 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2541 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2543 dump_graph_from_list(f, get_irp_irg(i));
2548 /* dump type info */
2549 current_ir_graph = irg;
2550 type_walk_irg(irg, dump_type_info, NULL, f);
2551 inc_irg_visited(get_const_code_irg());
2553 /* dump edges from graph to type info */
2554 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2557 dump_const_local = rem_dump_const_local;
2558 current_ir_graph = rem;
2562 /*---------------------------------------------------------------------*/
2563 /* The following routines dump a control flow graph. */
2564 /*---------------------------------------------------------------------*/
2567 dump_block_to_cfg(ir_node *block, void *env) {
2572 if (is_Block(block)) {
2573 /* This is a block. Dump a node for the block. */
2574 fprintf(F, "node: {title: \""); PRINT_NODEID(block);
2575 fprintf(F, "\" label: \"");
2576 if (block == get_irg_start_block(get_irn_irg(block)))
2577 fprintf(F, "Start ");
2578 if (block == get_irg_end_block(get_irn_irg(block)))
2581 fprintf(F, "%s ", get_op_name(get_irn_op(block)));
2582 PRINT_NODEID(block);
2584 fprintf(F, "info1:\"");
2586 /* the generic version. */
2587 dump_irnode_to_file(F, block);
2589 /* Check whether we have bad predecessors to color the block. */
2590 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2591 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2594 fprintf(F, "\""); /* closing quote of info */
2596 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2597 (block == get_irg_end_block(get_irn_irg(block))) )
2598 fprintf(F, " color:blue ");
2600 fprintf(F, " color:yellow ");
2603 /* Dump the edges */
2604 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2605 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2606 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2607 fprintf(F, "edge: { sourcename: \"");
2608 PRINT_NODEID(block);
2609 fprintf(F, "\" targetname: \"");
2611 fprintf(F, "\"}\n");
2614 /* Dump dominator/postdominator edge */
2615 if (dump_dominator_information_flag) {
2616 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2617 pred = get_Block_idom(block);
2618 fprintf(F, "edge: { sourcename: \"");
2619 PRINT_NODEID(block);
2620 fprintf(F, "\" targetname: \"");
2622 fprintf(F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2624 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2625 pred = get_Block_ipostdom(block);
2626 fprintf(F, "edge: { sourcename: \"");
2627 PRINT_NODEID(block);
2628 fprintf(F, "\" targetname: \"");
2630 fprintf(F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2637 dump_cfg(ir_graph *irg, const char *suffix)
2640 /* if a filter is set, dump only the irg's that match the filter */
2641 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2644 f = vcg_open(irg, suffix, "-cfg");
2646 ir_graph *rem = current_ir_graph;
2647 int ipv = get_interprocedural_view();
2649 current_ir_graph = irg;
2650 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2653 printf("Warning: dumping cfg not in interprocedural view!\n");
2654 set_interprocedural_view(0);
2657 /* walk over the blocks in the graph */
2658 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2659 dump_node(f, get_irg_bad(irg));
2661 set_interprocedural_view(ipv);
2663 current_ir_graph = rem;
2668 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2669 if (pset_find_ptr(mark_set, n)) return;
2671 pset_insert_ptr(mark_set, n);
2674 int i, start = is_Block(n) ? 0 : -1;
2675 dump_whole_node(n, F);
2676 for (i = start; i < get_irn_arity(n); ++i)
2677 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2680 /* Don't dump edges to nodes further out. These might be edges to
2681 nodes we already dumped, if there is a shorter path to these. */
2685 static int subgraph_counter = 0;
2686 void dump_subgraph(ir_node *root, int depth, const char *suffix) {
2690 sprintf(buf, "-subg_%03d", subgraph_counter++);
2691 F = vcg_open(get_irn_irg(root), suffix, buf);
2693 pset *mark_set = pset_new_ptr(1);
2694 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2695 descend_and_dump(F, root, depth, mark_set);
2702 static int weight_overall(int rec, int loop) {
2703 return 2*rec + loop;
2706 static int compute_color(int my, int max) {
2713 /* if small, scale to the full color range. */
2715 my = my * (n_colors/max);
2717 step = 1 + (max / n_colors);
2721 return base_color + n_colors - color;
2725 * Calculate a entity color depending on it's execution propability.
2727 static int get_entity_color(ir_entity *ent) {
2728 ir_graph *irg = get_entity_irg(ent);
2732 int rec_depth = get_irg_recursion_depth(irg);
2733 int loop_depth = get_irg_loop_depth(irg);
2734 int overall_depth = weight_overall(rec_depth, loop_depth);
2736 int max_rec_depth = irp->max_callgraph_recursion_depth;
2737 int max_loop_depth = irp->max_callgraph_loop_depth;
2738 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2740 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2741 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2742 int my_overall_color = compute_color(overall_depth, max_overall_depth);
2744 return my_overall_color;
2748 void dump_callgraph(const char *suffix) {
2749 FILE *F = vcg_open_name("Callgraph", suffix);
2752 int i, rem = edge_label, colorize;
2754 dump_vcg_header(F, "Callgraph", NULL);
2756 colorize = get_irp_callgraph_state() == irp_callgraph_and_calltree_consistent;
2758 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2759 ir_graph *irg = get_irp_irg(i);
2760 ir_entity *ent = get_irg_entity(irg);
2761 int j, n_callees = get_irg_n_callees(irg);
2764 color = colorize ? get_entity_color(ent) : ird_color_green;
2765 dump_entity_node(F, ent, color);
2766 for (j = 0; j < n_callees; ++j) {
2767 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2768 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2769 int be = is_irg_callee_backedge(irg, j);
2772 "label:\"recursion %d\" color:%d" :
2773 "label:\"calls %d\" color:%d";
2774 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), color);
2783 /* Dump all irgs in interprocedural view to a single file. */
2784 void dump_all_cg_block_graph(const char *suffix) {
2785 FILE *f = vcg_open_name("All_graphs", suffix);
2789 int rem_view = get_interprocedural_view();
2791 set_interprocedural_view(1);
2792 dump_vcg_header(f, "All_graphs", NULL);
2794 /* collect nodes in all irgs reachable in call graph*/
2795 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2796 ird_set_irg_link(get_irp_irg(i), NULL);
2798 cg_walk(clear_link, collect_node, NULL);
2800 /* dump all graphs */
2801 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2802 current_ir_graph = get_irp_irg(i);
2803 assert(ird_get_irg_link(current_ir_graph));
2804 dump_graph_from_list(f, current_ir_graph);
2805 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2809 set_interprocedural_view(rem_view);
2813 /*---------------------------------------------------------------------*/
2814 /* the following routines dumps type information without any ir nodes. */
2815 /*---------------------------------------------------------------------*/
2818 dump_type_graph(ir_graph *irg, const char *suffix)
2822 /* if a filter is set, dump only the irg's that match the filter */
2823 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2825 f = vcg_open(irg, suffix, "-type");
2827 ir_graph *rem = current_ir_graph;
2828 current_ir_graph = irg;
2830 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2832 /* walk over the blocks in the graph */
2833 type_walk_irg(irg, dump_type_info, NULL, f);
2834 /* The walker for the const code can be called several times for the
2835 same (sub) expression. So that no nodes are dumped several times
2836 we decrease the visited flag of the corresponding graph after each
2837 walk. So now increase it finally. */
2838 inc_irg_visited(get_const_code_irg());
2841 current_ir_graph = rem;
2846 dump_all_types(const char *suffix)
2848 FILE *f = vcg_open_name("All_types", suffix);
2850 dump_vcg_header(f, "All_types", NULL);
2851 type_walk(dump_type_info, NULL, f);
2852 inc_irg_visited(get_const_code_irg());
2858 dump_class_hierarchy(int entities, const char *suffix)
2860 FILE *f = vcg_open_name("class_hierarchy", suffix);
2865 env.dump_ent = entities;
2866 dump_vcg_header(f, "class_hierarchy", NULL);
2867 type_walk(dump_class_hierarchy_node, NULL, &env);
2872 /*---------------------------------------------------------------------*/
2873 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2875 /* dump_ir_block_graph */
2877 /* dump_type_graph */
2878 /* dump_ir_graph_w_types */
2879 /*---------------------------------------------------------------------*/
2881 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2883 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2884 dmp_grph(get_irp_irg(i), suffix);
2888 /*--------------------------------------------------------------------------------*
2889 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2890 * packed together in one subgraph/box *
2891 *--------------------------------------------------------------------------------*/
2893 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2894 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2896 ir_loop *son = NULL;
2898 /* Dump a new loop node. */
2899 dump_loop_node(F, loop);
2901 /* Dump the loop elements. */
2903 for(i = 0; i < get_loop_n_elements(loop); i++) {
2904 le = get_loop_element(loop, i);
2906 if (get_kind(son) == k_ir_loop) {
2908 /* We are a loop son -> Recurse */
2910 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2911 fprintf(F, "\" }\n");
2912 fprintf(F, "edge: {sourcename: \"");
2914 fprintf(F, "\" targetname: \"");
2916 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2917 loop_node_started = 0;
2919 dump_loop_son_edge(F, loop, son_number++);
2920 dump_loops_standalone(F, son);
2921 } else if (get_kind(son) == k_ir_node) {
2922 /* We are a loop node -> Collect firm nodes */
2924 ir_node *n = le.node;
2927 if (!loop_node_started) {
2928 /* Start a new node which contains all firm nodes of the current loop */
2929 fprintf(F, "node: { title: \"");
2931 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
2932 loop_node_started = 1;
2937 bad |= dump_node_label(F, n);
2938 /* Causes indeterministic output: if (is_Block(n)) fprintf(F, "\t ->%d", (int)get_irn_link(n)); */
2939 if (has_backedges(n)) fprintf(F, "\t loop head!");
2940 } else { /* for callgraph loop tree */
2942 assert(get_kind(son) == k_ir_graph);
2944 /* We are a loop node -> Collect firm graphs */
2945 n = (ir_graph *)le.node;
2946 if (!loop_node_started) {
2947 /* Start a new node which contains all firm nodes of the current loop */
2948 fprintf(F, "node: { title: \"");
2950 fprintf(F, "-%d-nodes\" color: lightyellow label: \"", i);
2951 loop_node_started = 1;
2955 fprintf(F, " %s", get_irg_dump_name(n));
2956 /* fprintf(F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2960 if (loop_node_started) {
2961 fprintf(F, "\" }\n");
2962 fprintf(F, "edge: {sourcename: \"");
2964 fprintf(F, "\" targetname: \"");
2966 fprintf(F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2967 loop_node_started = 0;
2971 void dump_loop_tree(ir_graph *irg, const char *suffix)
2975 /* if a filter is set, dump only the irg's that match the filter */
2976 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2978 f = vcg_open(irg, suffix, "-looptree");
2980 ir_graph *rem = current_ir_graph;
2981 int el_rem = edge_label;
2983 current_ir_graph = irg;
2986 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2988 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2992 edge_label = el_rem;
2993 current_ir_graph = rem;
2997 void dump_callgraph_loop_tree(const char *suffix) {
2999 F = vcg_open_name("Callgraph_looptree", suffix);
3000 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
3001 dump_loops_standalone(F, irp->outermost_cg_loop);
3006 /*-----------------------------------------------------------------------------*/
3007 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
3008 /*-----------------------------------------------------------------------------*/
3010 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
3011 int i, son_number = 0, node_number = 0;
3013 if (dump_loop_information_flag) dump_loop_node(F, loop);
3015 for (i = 0; i < get_loop_n_elements(loop); i++) {
3016 loop_element le = get_loop_element(loop, i);
3017 if (*(le.kind) == k_ir_loop) {
3018 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3020 collect_nodeloop(F, le.son, loopnodes);
3022 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3023 eset_insert(loopnodes, le.node);
3028 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
3031 for(i = 0; i < get_loop_n_elements(loop); i++) {
3032 loop_element le = get_loop_element(loop, i);
3033 if (*(le.kind) == k_ir_loop) {
3035 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3037 if (is_Block(le.node)) start = 0; else start = -1;
3038 for (j = start; j < get_irn_arity(le.node); j++) {
3039 ir_node *pred = get_irn_n(le.node, j);
3040 if (!eset_contains(loopnodes, pred)) {
3041 eset_insert(extnodes, pred);
3042 if (!is_Block(pred)) {
3043 pred = get_nodes_block(pred);
3044 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3052 void dump_loop(ir_loop *l, const char *suffix) {
3056 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3057 F = vcg_open_name(name, suffix);
3059 eset *loopnodes = eset_create();
3060 eset *extnodes = eset_create();
3063 dump_vcg_header(F, name, NULL);
3065 /* collect all nodes to dump */
3066 collect_nodeloop(F, l, loopnodes);
3067 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3069 /* build block lists */
3070 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3071 set_irn_link(n, NULL);
3072 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3073 set_irn_link(n, NULL);
3074 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes)) {
3076 b = get_nodes_block(n);
3077 set_irn_link(n, get_irn_link(b));
3081 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes)) {
3083 b = get_nodes_block(n);
3084 set_irn_link(n, get_irn_link(b));
3089 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes)) {
3091 fprintf(F, "graph: { title: \"");
3093 fprintf(F, "\" label: \"");
3094 dump_node_opcode(F, b);
3095 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3096 fprintf(F, "\" status:clustered color:yellow\n");
3098 /* dump the blocks edges */
3099 dump_ir_data_edges(F, b);
3101 /* dump the nodes that go into the block */
3102 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3103 if (eset_contains(extnodes, n))
3104 overrule_nodecolor = ird_color_lightblue;
3106 overrule_nodecolor = ird_color_default;
3107 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3110 /* Close the vcg information for the block */
3112 dump_const_node_local(F, b);
3116 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes)) {
3118 fprintf(F, "graph: { title: \"");
3120 fprintf(F, "\" label: \"");
3121 dump_node_opcode(F, b);
3122 fprintf(F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3123 fprintf(F, "\" status:clustered color:lightblue\n");
3125 /* dump the nodes that go into the block */
3126 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3127 if (!eset_contains(loopnodes, n))
3128 overrule_nodecolor = ird_color_lightblue;
3130 overrule_nodecolor = ird_color_default;
3131 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3134 /* Close the vcg information for the block */
3136 dump_const_node_local(F, b);
3140 eset_destroy(loopnodes);
3141 eset_destroy(extnodes);