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 /** An additional edge hook. */
101 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
103 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
105 dump_node_edge_hook = func;
108 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
110 return dump_node_edge_hook;
114 static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
116 void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func)
118 dump_block_edge_hook = func;
121 DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void)
123 return dump_node_edge_hook;
127 /** The vcg node attribute hook. */
128 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
129 /** The vcg node attribute hook. */
130 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
131 /** The vcg edge attribute hook. */
132 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
134 /* set the ir graph hook */
135 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
136 dump_ir_graph_hook = hook;
138 /* set the node attribute hook */
139 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
140 dump_node_vcgattr_hook = hook;
142 /* set the edge attribute hook */
143 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
144 dump_edge_vcgattr_hook = hook;
147 int get_opt_dump_const_local(void) {
148 if (!dump_out_edge_flag && !dump_loop_information_flag)
149 return dump_const_local;
154 void only_dump_method_with_name(ident *name) {
155 dump_file_filter_id = name;
158 ident *get_dump_file_filter_ident(void) {
159 return dump_file_filter_id;
162 /** Returns non-zero if dump file filter is not set, or if it is a
164 int is_filtered_dump_name(ident *name) {
165 if (!dump_file_filter_id) return 1;
166 return id_is_prefix(dump_file_filter_id, name);
169 /* To turn off display of edge labels. Edge labels often cause xvcg to
170 abort with a segmentation fault. */
171 void turn_off_edge_labels(void) {
175 void dump_consts_local(int flag) {
176 dump_const_local = flag;
179 void dump_constant_entity_values(int flag) {
180 const_entities = flag;
183 void dump_keepalive_edges(int flag) {
184 dump_keepalive = flag;
187 int get_opt_dump_keepalive_edges(void) {
188 return dump_keepalive;
191 void dump_out_edges(int flag) {
192 dump_out_edge_flag = flag;
195 void dump_dominator_information(int flag) {
196 dump_dominator_information_flag = flag;
199 void dump_loop_information(int flag) {
200 dump_loop_information_flag = flag;
203 void dump_backedge_information(int flag) {
204 dump_backedge_information_flag = flag;
207 /* Dump the information of type field specified in ana/irtypeinfo.h.
208 * If the flag is set, the type name is output in [] in the node label,
209 * else it is output as info.
211 void set_opt_dump_analysed_type_info(int flag) {
212 opt_dump_analysed_type_info = flag;
215 void dump_pointer_values_to_info(int flag) {
216 opt_dump_pointer_values_to_info = flag;
219 void dump_ld_names(int flag) {
223 void dump_all_anchors(int flag) {
227 /* -------------- some extended helper functions ----------------- */
230 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
231 * in the later case, sets bad
233 const char *get_mode_name_ex(ir_mode *mode, int *bad)
236 return get_mode_name(mode);
242 * returns the name of a type or <ERROR> if mode is NOT a mode object.
243 * in the later case, sets bad
245 const char *get_type_name_ex(ir_type *tp, int *bad)
248 return get_type_name(tp);
254 * printf the VCG color
256 static void print_vcg_color(FILE *F, dumper_colors color) {
257 static const char *color_names[32] = {
258 "white", "blue", "red", "green",
259 "yellow", "magenta", "cyan", "darkgray",
260 "darkblue", "darkred", "darkgreen", "darkyellow",
261 "darkmagenta", "darkcyan", "gold", "lightgray",
262 "lightblue", "lightred", "lightgreen", "lightyellow",
263 "lightmagenta", "lightcyan", "lilac", "turquoise",
264 "aquamarine", "khaki", "purple", "yellowgreen",
265 "pink", "orange", "orchid", "black"
268 if (color != ird_color_default)
269 fprintf(F, "color:%s", color_names[color]);
273 * prints the edge from a type S to a type T with additional info fmt, ...
276 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
281 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
282 fprintf(F, " targetname: "); PRINT_TYPEID(T);
283 vfprintf(F, fmt, ap);
289 * prints the edge from a type T to an entity E with additional info fmt, ...
292 static void print_type_ent_edge(FILE *F, ir_type *T, ir_entity *E, const char *fmt, ...)
297 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
298 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
299 vfprintf(F, fmt, ap);
305 * prints the edge from an entity E to an entity T with additional info fmt, ...
308 static void print_ent_ent_edge(FILE *F, ir_entity *E, ir_entity *T, int backedge, const char *fmt, ...)
314 fprintf(F, "backedge: { sourcename: \"");
316 fprintf(F, "edge: { sourcename: \"");
318 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
319 vfprintf(F, fmt, ap);
325 * prints the edge from an entity E to a type T with additional info fmt, ...
328 static void print_ent_type_edge(FILE *F, ir_entity *E, ir_type *T, const char *fmt, ...)
333 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
334 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
335 vfprintf(F, fmt, ap);
341 * prints the edge from a node N to a type T with additional info fmt, ...
344 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
349 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
350 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
351 vfprintf(F, fmt, ap);
357 * prints the edge from a node N to an entity E with additional info fmt, ...
360 static void print_node_ent_edge(FILE *F, const ir_node *N, ir_entity *E, const char *fmt, ...)
365 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
366 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
368 vfprintf(F, fmt, ap);
374 * prints the edge from an entity E to a node N with additional info fmt, ...
377 static void print_ent_node_edge(FILE *F, ir_entity *E, const ir_node *N, const char *fmt, ...)
382 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
383 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
384 vfprintf(F, fmt, ap);
390 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
393 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
398 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
399 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
400 vfprintf(F, fmt, ap);
405 /*-----------------------------------------------------------------*/
406 /* global and ahead declarations */
407 /*-----------------------------------------------------------------*/
409 static void dump_whole_node(ir_node *n, void *env);
410 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
412 /*-----------------------------------------------------------------*/
413 /* Helper functions. */
414 /*-----------------------------------------------------------------*/
417 * This map is used as a private link attr to be able to call dumper
418 * anywhere without destroying link fields.
420 static pmap *irdump_link_map = NULL;
422 /** NOT A STANDARD LIBFIRM INIT METHOD
424 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
425 * are off, we want to have as few interferences as possible. Therefore the
426 * initialization is performed lazily and not called from within init_firm.
428 * Creates the link attribute map. */
429 static void init_irdump(void) {
430 /* We need a new, empty map. */
431 if (irdump_link_map) pmap_destroy(irdump_link_map);
432 irdump_link_map = pmap_create();
433 if (!dump_file_filter_id)
434 dump_file_filter_id = new_id_from_str("");
437 * Returns the private link field.
439 static void *ird_get_irn_link(ir_node *n) {
441 if (!irdump_link_map) return NULL;
443 if (pmap_contains(irdump_link_map, (void *)n))
444 res = pmap_get(irdump_link_map, (void *)n);
449 * Sets the private link field.
451 static void ird_set_irn_link(ir_node *n, void *x) {
452 if (!irdump_link_map)
454 pmap_insert(irdump_link_map, (void *)n, x);
458 * Gets the private link field of an irg.
460 static void *ird_get_irg_link(ir_graph *irg) {
462 if (!irdump_link_map) return NULL;
464 if (pmap_contains(irdump_link_map, (void *)irg))
465 res = pmap_get(irdump_link_map, (void *)irg);
470 * Sets the private link field of an irg.
472 static void ird_set_irg_link(ir_graph *irg, void *x) {
473 if (!irdump_link_map) init_irdump();
474 pmap_insert(irdump_link_map, (void *)irg, x);
478 * Walker, clears the private link field.
480 static void clear_link(ir_node * node, void * env) {
481 ird_set_irn_link(node, NULL);
485 * If the entity has a ld_name, returns it if the dump_ld_name is set,
486 * else returns the name of the entity.
488 static const char *_get_ent_dump_name(ir_entity *ent, int dump_ld_name) {
490 return "<NULL entity>";
492 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
493 if (ent->ld_name) return get_id_str(ent->ld_name);
495 return get_id_str(ent->name);
499 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
500 * else returns the name of the entity.
502 const char *get_ent_dump_name(ir_entity *ent) {
503 return _get_ent_dump_name(ent, dump_ld_name);
506 /* Returns the name of an IRG. */
507 const char *get_irg_dump_name(ir_graph *irg) {
508 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
509 return _get_ent_dump_name(get_irg_entity(irg), 1);
513 * Returns non-zero if a node is in floating state.
515 static int node_floats(ir_node *n) {
516 return ((get_irn_pinned(n) == op_pin_state_floats) &&
517 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
521 * Walker that visits the anchors
523 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
524 irg_walk_graph(irg, pre, post, env);
529 for (i = anchor_max - 1; i >= 0; --i) {
530 ir_node *n = irg->anchors[i];
533 /* reset the visit flag: will be increase in the walker */
534 set_irg_visited(irg, get_irg_visited(irg) - 1);
535 irg_walk(n, pre, post, env);
542 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
544 static void collect_node(ir_node * node, void *env) {
547 || get_irn_op(node) == op_Bad
548 || get_irn_op(node) == op_Unknown
549 || get_irn_op(node) == op_NoMem) {
550 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
551 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
552 ARR_APP1(ir_node *, arr, node);
553 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
555 ir_node * block = get_nodes_block(node);
558 /* this node is in a Bad block, so we must place it into the graph's list */
559 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
560 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
561 ARR_APP1(ir_node *, arr, node);
562 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
565 ird_set_irn_link(node, ird_get_irn_link(block));
566 ird_set_irn_link(block, node);
571 /** Construct lists to walk ir block-wise.
573 * Collects all blocks, nodes not op_pin_state_pinned,
574 * Bad, NoMem and Unknown into a flexible array in link field of
575 * irg they belong to. Sets the irg link field to NULL in all
576 * graphs not visited.
577 * Free the list with DEL_ARR_F().
579 static ir_node **construct_block_lists(ir_graph *irg) {
580 int i, rem_view = get_interprocedural_view();
581 ir_graph *rem = current_ir_graph;
582 current_ir_graph = irg;
584 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
585 ird_set_irg_link(get_irp_irg(i), NULL);
587 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
589 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
590 set_interprocedural_view(0);
592 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
593 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
594 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
595 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
597 set_interprocedural_view(rem_view);
599 current_ir_graph = rem;
600 return ird_get_irg_link(irg);
603 typedef struct _list_tuple {
605 ir_extblk **extbb_list;
608 /** Construct lists to walk IR extended block-wise.
609 * Free the lists in the tuple with DEL_ARR_F().
610 * Sets the irg link field to NULL in all
611 * graphs not visited.
613 static list_tuple *construct_extblock_lists(ir_graph *irg) {
614 ir_node **blk_list = construct_block_lists(irg);
616 ir_graph *rem = current_ir_graph;
617 list_tuple *lists = xmalloc(sizeof(*lists));
619 current_ir_graph = irg;
621 lists->blk_list = NEW_ARR_F(ir_node *, 0);
622 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
624 inc_irg_block_visited(irg);
625 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
628 if (is_Block(blk_list[i])) {
629 ext = get_Block_extbb(blk_list[i]);
631 if (extbb_not_visited(ext)) {
632 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
633 mark_extbb_visited(ext);
637 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
641 current_ir_graph = rem;
642 ird_set_irg_link(irg, lists);
646 /*-----------------------------------------------------------------*/
647 /* Routines to dump information about a single ir node. */
648 /*-----------------------------------------------------------------*/
651 * dump the name of a node n to the File F.
653 int dump_node_opcode(FILE *F, ir_node *n)
656 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
658 /* call the dump_node operation if available */
660 return ops->dump_node(n, F, dump_node_opcode_txt);
662 /* implementation for default nodes */
663 switch (get_irn_opcode(n)) {
668 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
669 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
674 switch (get_SymConst_kind(n)) {
675 case symconst_addr_name:
676 /* don't use get_SymConst_ptr_info as it mangles the name. */
677 fprintf(F, "SymC %s", get_id_str(get_SymConst_name(n)));
679 case symconst_addr_ent:
680 fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
682 case symconst_ofs_ent:
683 fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
685 case symconst_type_tag:
686 fprintf(F, "SymC %s tag", get_type_name_ex(get_SymConst_type(n), &bad));
688 case symconst_type_size:
689 fprintf(F, "SymC %s size", get_type_name_ex(get_SymConst_type(n), &bad));
691 case symconst_type_align:
692 fprintf(F, "SymC %s align", get_type_name_ex(get_SymConst_type(n), &bad));
694 case symconst_enum_const:
695 fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
701 if (!get_interprocedural_view())
708 ir_node *pred = get_Proj_pred(n);
710 if (get_irn_opcode(pred) == iro_Cond
711 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
712 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
713 fprintf (F, "defProj");
721 if (get_interprocedural_view()) {
722 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
727 case iro_CallBegin: {
728 ir_node *addr = get_CallBegin_ptr(n);
729 ir_entity *ent = NULL;
730 if (get_irn_op(addr) == op_Sel)
731 ent = get_Sel_entity(addr);
732 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
733 ent = get_SymConst_entity(addr);
734 fprintf (F, "%s", get_irn_opname(n));
735 if (ent) fprintf (F, " %s", get_entity_name(ent));
739 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
742 fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
745 if (get_Conv_strict(n))
746 fprintf (F, "strict");
747 fprintf (F, "%s", get_irn_opname(n));
752 fprintf (F, "%s", get_irn_opname(n));
759 * Dump the mode of a node n to a file F.
760 * Ignore modes that are "always known".
762 static int dump_node_mode(FILE *F, ir_node *n)
765 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
768 /* call the dump_node operation if available */
770 return ops->dump_node(n, F, dump_node_mode_txt);
772 /* default implementation */
773 iro = get_irn_opcode(n);
785 ir_mode *mode = get_irn_mode(n);
787 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
788 (mode != mode_T || iro == iro_Proj))
789 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
797 * Dump the type of a node n to a file F if it's known.
799 static int dump_node_typeinfo(FILE *F, ir_node *n) {
802 if (opt_dump_analysed_type_info) {
803 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
804 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
805 ir_type *tp = get_irn_typeinfo_type(n);
806 if (tp != firm_none_type)
807 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
815 typedef struct _pns_lookup {
816 long nr; /**< the proj number */
817 const char *name; /**< the name of the Proj */
820 typedef struct _proj_lookup {
821 opcode code; /**< the opcode of the Proj predecessor */
822 unsigned num_data; /**< number of data entries */
823 const pns_lookup_t *data; /**< the data */
826 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
828 /** the lookup table for Proj(Start) names */
829 static const pns_lookup_t start_lut[] = {
830 #define X(a) { pn_Start_##a, #a }
840 /** the lookup table for Proj(Cond) names */
841 static const pns_lookup_t cond_lut[] = {
842 #define X(a) { pn_Cond_##a, #a }
848 /** the lookup table for Proj(Call) names */
849 static const pns_lookup_t call_lut[] = {
850 #define X(a) { pn_Call_##a, #a }
859 /** the lookup table for Proj(Quot) names */
860 static const pns_lookup_t quot_lut[] = {
861 #define X(a) { pn_Quot_##a, #a }
868 /** the lookup table for Proj(DivMod) names */
869 static const pns_lookup_t divmod_lut[] = {
870 #define X(a) { pn_DivMod_##a, #a }
878 /** the lookup table for Proj(Div) names */
879 static const pns_lookup_t div_lut[] = {
880 #define X(a) { pn_Div_##a, #a }
887 /** the lookup table for Proj(Mod) names */
888 static const pns_lookup_t mod_lut[] = {
889 #define X(a) { pn_Mod_##a, #a }
896 /** the lookup table for Proj(Load) names */
897 static const pns_lookup_t load_lut[] = {
898 #define X(a) { pn_Load_##a, #a }
905 /** the lookup table for Proj(Store) names */
906 static const pns_lookup_t store_lut[] = {
907 #define X(a) { pn_Store_##a, #a }
913 /** the lookup table for Proj(Alloc) names */
914 static const pns_lookup_t alloc_lut[] = {
915 #define X(a) { pn_Alloc_##a, #a }
922 /** the lookup table for Proj(CopyB) names */
923 static const pns_lookup_t copyb_lut[] = {
924 #define X(a) { pn_CopyB_##a, #a }
931 /** the lookup table for Proj(InstOf) names */
932 static const pns_lookup_t instof_lut[] = {
933 #define X(a) { pn_InstOf_##a, #a }
941 /** the lookup table for Proj(Raise) names */
942 static const pns_lookup_t raise_lut[] = {
943 #define X(a) { pn_Raise_##a, #a }
949 /** the lookup table for Proj(Bound) names */
950 static const pns_lookup_t bound_lut[] = {
951 #define X(a) { pn_Bound_##a, #a }
958 /** the Proj lookup table */
959 static const proj_lookup_t proj_lut[] = {
960 #define E(a) ARR_SIZE(a), a
961 { iro_Start, E(start_lut) },
962 { iro_Cond, E(cond_lut) },
963 { iro_Call, E(call_lut) },
964 { iro_Quot, E(quot_lut) },
965 { iro_DivMod, E(divmod_lut) },
966 { iro_Div, E(div_lut) },
967 { iro_Mod, E(mod_lut) },
968 { iro_Load, E(load_lut) },
969 { iro_Store, E(store_lut) },
970 { iro_Alloc, E(alloc_lut) },
971 { iro_CopyB, E(copyb_lut) },
972 { iro_InstOf, E(instof_lut) },
973 { iro_Raise, E(raise_lut) },
974 { iro_Bound, E(bound_lut) }
979 * Dump additional node attributes of some nodes to a file F.
982 dump_node_nodeattr(FILE *F, ir_node *n)
988 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
990 /* call the dump_node operation if available */
992 return ops->dump_node(n, F, dump_node_nodeattr_txt);
994 switch (get_irn_opcode(n)) {
996 if (0 && get_interprocedural_view()) {
997 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
1002 pred = get_Proj_pred(n);
1003 proj_nr = get_Proj_proj(n);
1005 code = get_irn_opcode(pred);
1007 if (code == iro_Cmp)
1008 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
1009 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1010 fprintf (F, "Arg %ld ", proj_nr);
1011 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1012 fprintf (F, "%ld ", proj_nr);
1014 unsigned i, j, f = 0;
1016 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
1017 if (code == proj_lut[i].code) {
1018 for (j = 0; j < proj_lut[i].num_data; ++j) {
1019 if (proj_nr == proj_lut[i].data[j].nr) {
1020 fprintf (F, "%s ", proj_lut[i].data[j].name);
1029 fprintf (F, "%ld ", proj_nr);
1030 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1031 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1032 fprintf(F, "PRED ");
1033 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1034 fprintf(F, "PRED ");
1039 proj_nr = get_Filter_proj(n);
1040 if (! get_interprocedural_view()) {
1042 pred = get_Filter_pred(n);
1046 fprintf (F, "%ld ", proj_nr);
1049 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1052 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1055 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1058 fprintf (F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1069 #include "execution_frequency.h"
1070 #include "callgraph.h"
1072 void dump_node_ana_vals(FILE *F, ir_node *n) {
1074 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1075 get_irn_exec_freq(n),
1076 get_irg_method_execution_frequency(get_irn_irg(n)),
1077 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1078 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1083 /* Dumps a node label without the enclosing ". */
1084 int dump_node_label(FILE *F, ir_node *n) {
1087 bad |= dump_node_opcode(F, n);
1088 bad |= dump_node_mode(F, n);
1090 bad |= dump_node_typeinfo(F, n);
1091 bad |= dump_node_nodeattr(F, n);
1092 fprintf(F, "%ld:%d", get_irn_node_nr(n), get_irn_idx(n));
1099 * Dumps the attributes of a node n into the file F.
1100 * Currently this is only the color of a node.
1102 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1107 print_vcg_color(F, ird_color_red);
1111 if (dump_node_vcgattr_hook)
1112 if (dump_node_vcgattr_hook(F, node, local))
1115 n = local ? local : node;
1117 if (overrule_nodecolor != ird_color_default) {
1118 print_vcg_color(F, overrule_nodecolor);
1122 switch (get_irn_opcode(n)) {
1129 print_vcg_color(F, ird_color_blue);
1132 if (is_Block_dead(n))
1133 print_vcg_color(F, ird_color_lightred);
1135 print_vcg_color(F, ird_color_lightyellow);
1138 print_vcg_color(F, ird_color_green);
1142 print_vcg_color(F, ird_color_gold);
1145 print_vcg_color(F, ird_color_orchid);
1151 print_vcg_color(F, ird_color_yellow);
1154 PRINT_DEFAULT_NODE_ATTR;
1158 /* Adds a new node info dumper callback. */
1159 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1161 hook_entry_t *info = xmalloc(sizeof(*info));
1163 info->hook._hook_node_info = cb;
1164 info->context = data;
1165 register_hook(hook_node_info, info);
1170 /* Remove a previously added info dumper callback. */
1171 void dump_remv_node_info_callback(void *handle)
1173 hook_entry_t *info = handle;
1174 unregister_hook(hook_node_info, info);
1179 * Dump the node information of a node n to a file F.
1181 static INLINE int dump_node_info(FILE *F, ir_node *n)
1184 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1186 fprintf (F, " info1: \"");
1187 bad = dump_irnode_to_file(F, n);
1188 /* call the dump_node operation if available */
1190 bad = ops->dump_node(n, F, dump_node_info_txt);
1192 /* allow additional info to be added */
1193 hook_node_info(F, n);
1200 * checks whether a node is "constant-like" ie can be treated "block-less"
1203 int is_constlike_node(ir_node *n) {
1204 ir_op *op = get_irn_op(n);
1205 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1209 /** outputs the predecessors of n, that are constants, local. I.e.,
1210 generates a copy of the constant predecessors for each node called with. */
1211 static void dump_const_node_local(FILE *F, ir_node *n) {
1213 if (!get_opt_dump_const_local()) return;
1215 /* Use visited flag to avoid outputting nodes twice.
1216 initialize it first. */
1217 for (i = 0; i < get_irn_arity(n); i++) {
1218 ir_node *con = get_irn_n(n, i);
1219 if (is_constlike_node(con)) {
1220 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
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) && irn_not_visited(con)) {
1229 mark_irn_visited(con);
1230 /* Generate a new name for the node by appending the names of
1232 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1233 fprintf(F, " label: \"");
1234 bad |= dump_node_label(F, con);
1236 bad |= dump_node_info(F, con);
1237 dump_node_vcgattr(F, n, con, bad);
1243 /** If the block of an edge is a const_like node, dump it local with an edge */
1244 static void dump_const_block_local(FILE *F, ir_node *n) {
1247 if (!get_opt_dump_const_local()) return;
1249 blk = get_nodes_block(n);
1250 if (is_constlike_node(blk)) {
1253 /* Generate a new name for the node by appending the names of
1255 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1256 fprintf(F, "\" label: \"");
1257 bad |= dump_node_label(F, blk);
1259 bad |= dump_node_info(F, blk);
1260 dump_node_vcgattr(F, n, blk, bad);
1263 fprintf (F, "edge: { sourcename: \"");
1265 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1267 if (dump_edge_vcgattr_hook) {
1269 if (dump_edge_vcgattr_hook(F, n, -1)) {
1274 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1279 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1284 * prints the error message of a node to a file F as info2.
1286 static void INLINE print_node_error(FILE *F, const char *err_msg)
1291 fprintf (F, " info2: \"%s\"", err_msg);
1295 * prints debug messages of a node to file F as info3.
1297 static void print_dbg_info(FILE *F, dbg_info *dbg)
1301 if (__dbg_info_snprint) {
1303 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1304 fprintf (F, " info3: \"%s\"\n", buf);
1311 static void dump_node(FILE *F, ir_node *n)
1316 if (get_opt_dump_const_local() && is_constlike_node(n))
1319 /* dump this node */
1320 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1322 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1323 bad |= dump_node_label(F, n);
1324 dump_node_ana_vals(F, n);
1325 //dump_node_ana_info(F, n);
1327 bad |= dump_node_info(F, n);
1328 print_node_error(F, p);
1329 print_dbg_info(F, get_irn_dbg_info(n));
1330 dump_node_vcgattr(F, n, NULL, bad);
1332 dump_const_node_local(F, n);
1334 if(dump_node_edge_hook)
1335 dump_node_edge_hook(F, n);
1337 dump_irn_chi_term(F, n);
1338 dump_irn_state(F, n);
1342 /** dump the edge to the block this node belongs to */
1344 dump_ir_block_edge(FILE *F, ir_node *n) {
1345 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1346 if (is_no_Block(n)) {
1347 ir_node *block = get_nodes_block(n);
1349 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1350 dump_const_block_local(F, n);
1353 fprintf (F, "edge: { sourcename: \"");
1355 fprintf (F, "\" targetname: ");
1356 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1358 if (dump_edge_vcgattr_hook) {
1360 if (dump_edge_vcgattr_hook(F, n, -1)) {
1365 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1370 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1376 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1378 * do not use get_nodes_block() here, will fail
1379 * if the irg is not pinned.
1381 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1382 fprintf (F, INTRA_DATA_EDGE_ATTR);
1384 fprintf (F, INTER_DATA_EDGE_ATTR);
1388 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1390 * do not use get_nodes_block() here, will fail
1391 * if the irg is not pinned.
1393 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1394 fprintf (F, INTRA_MEM_EDGE_ATTR);
1396 fprintf (F, INTER_MEM_EDGE_ATTR);
1400 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1403 if (dump_edge_vcgattr_hook)
1404 if (dump_edge_vcgattr_hook(F, from, to))
1407 if (dump_backedge_information_flag && is_backedge(from, to))
1408 fprintf (F, BACK_EDGE_ATTR);
1410 switch (get_irn_opcode(from)) {
1412 fprintf (F, CF_EDGE_ATTR);
1414 case iro_Start: break;
1417 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1418 fprintf (F, CF_EDGE_ATTR);
1419 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1420 fprintf (F, INTER_MEM_EDGE_ATTR);
1424 if (is_Proj(from)) {
1425 if (get_irn_mode(from) == mode_M)
1426 print_mem_edge_vcgattr(F, from, to);
1427 else if (get_irn_mode(from) == mode_X)
1428 fprintf(F, CF_EDGE_ATTR);
1430 print_data_edge_vcgattr(F, from, to);
1432 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1433 print_mem_edge_vcgattr(F, from, to);
1434 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1435 fprintf (F, CF_EDGE_ATTR);
1437 print_data_edge_vcgattr(F, from, to);
1441 /* dump edges to our inputs */
1443 dump_ir_data_edges(FILE *F, ir_node *n) {
1445 unsigned long visited = get_irn_visited(n);
1447 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1450 /* dump the dependency edges. */
1451 for (i = 0; i < get_irn_deps(n); ++i) {
1452 ir_node *dep = get_irn_dep(n, i);
1455 fprintf(F, "edge: {sourcename: \"");
1457 fprintf(F, "\" targetname: ");
1458 if ((get_opt_dump_const_local()) && is_constlike_node(dep)) {
1459 PRINT_CONSTID(n, dep);
1465 fprintf(F, " label: \"%d\" ", i);
1466 fprintf(F, " color: darkgreen}\n");
1470 for (i = 0; i < get_irn_arity(n); i++) {
1471 ir_node * pred = get_irn_n(n, i);
1474 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1475 continue; /* pred not dumped */
1477 if (dump_backedge_information_flag && is_backedge(n, i))
1478 fprintf (F, "backedge: {sourcename: \"");
1480 fprintf (F, "edge: {sourcename: \"");
1482 fprintf (F, "\" targetname: ");
1483 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1484 PRINT_CONSTID(n, pred);
1486 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1488 fprintf (F, " label: \"%d\" ", i);
1489 print_edge_vcgattr(F, n, i);
1494 /** Dumps a node and its edges but not the block edge
1497 dump_node_wo_blockedge (ir_node *n, void *env) {
1500 dump_ir_data_edges(F, n);
1503 /** Dumps a node and its edges.
1506 dump_whole_node (ir_node *n, void *env) {
1508 dump_node_wo_blockedge(n, env);
1509 if (!node_floats(n)) dump_ir_block_edge(F, n);
1513 dump_const_node(ir_node *n, void *env) {
1514 if (is_Block(n)) return;
1515 dump_node_wo_blockedge(n, env);
1518 /***********************************************************************/
1519 /* the following routines dump the nodes/irgs bracketed to graphs. */
1520 /***********************************************************************/
1522 /** Dumps a constant expression as entity initializer, array bound ...
1524 static void dump_const_expression(FILE *F, ir_node *value) {
1525 ir_graph *rem = current_ir_graph;
1526 int rem_dump_const_local = dump_const_local;
1527 dump_const_local = 0;
1528 current_ir_graph = get_const_code_irg();
1529 irg_walk(value, dump_const_node, NULL, F);
1530 /* Decrease visited flag so that we walk with the same flag for the next
1531 expression. This guarantees that we don't dump the same node twice,
1532 as for const expressions cse is performed to save memory. */
1533 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1534 current_ir_graph = rem;
1535 dump_const_local = rem_dump_const_local;
1538 /** Dump a block as graph containing its nodes.
1540 * Expects to find nodes belonging to the block as list in its
1542 * Dumps the edges of all nodes including itself. */
1544 dump_whole_block(FILE *F, ir_node *block) {
1546 dumper_colors color = ird_color_yellow;
1548 assert(is_Block(block));
1550 fprintf(F, "graph: { title: \"");
1551 PRINT_NODEID(block);
1552 fprintf(F, "\" label: \"");
1553 dump_node_label(F, block);
1555 if (get_opt_dump_abstvals())
1556 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1559 /* colorize blocks */
1560 if (! get_Block_matured(block))
1561 color = ird_color_red;
1562 if (is_Block_dead(block))
1563 color = ird_color_orange;
1565 fprintf(F, "\" status:clustered ");
1566 print_vcg_color(F, color);
1569 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1570 dump_node_info(F, block);
1571 print_dbg_info(F, get_irn_dbg_info(block));
1573 /* dump the blocks edges */
1574 dump_ir_data_edges(F, block);
1576 if (dump_block_edge_hook)
1577 dump_block_edge_hook(F, block);
1579 /* dump the nodes that go into the block */
1580 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1582 dump_ir_data_edges(F, node);
1585 /* Close the vcg information for the block */
1587 dump_const_node_local(F, block);
1589 dump_irn_chi_term(F, block);
1594 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1595 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1597 dump_block_graph(FILE *F, ir_graph *irg) {
1599 ir_graph *rem = current_ir_graph;
1600 ir_node **arr = ird_get_irg_link(irg);
1601 current_ir_graph = irg;
1603 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1604 ir_node * node = arr[i];
1605 if (is_Block(node)) {
1606 /* Dumps the block and all the nodes in the block, which are to
1607 be found in Block->link. */
1608 dump_whole_block(F, node);
1610 /* Nodes that are not in a Block. */
1612 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1613 dump_const_block_local(F, node);
1615 dump_ir_data_edges(F, node);
1619 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1620 dump_loop_nodes_into_graph(F, irg);
1622 current_ir_graph = rem;
1626 * Dump the info for an irg.
1627 * Parsed by XVCG but not shown. use yComp.
1629 static void dump_graph_info(FILE *F, ir_graph *irg) {
1630 fprintf(F, "info1: \"");
1631 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1635 /** Dumps an irg as a graph clustered by block nodes.
1636 * If interprocedural view edges can point to nodes out of this graph.
1638 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1639 ir_entity *ent = get_irg_entity(irg);
1641 fprintf(F, "graph: { title: \"");
1643 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1644 get_ent_dump_name(ent));
1646 dump_graph_info(F, irg);
1647 print_dbg_info(F, get_entity_dbg_info(ent));
1649 dump_block_graph(F, irg);
1651 /* Close the vcg information for the irg */
1652 fprintf(F, "}\n\n");
1655 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1656 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1658 dump_extblock_graph(FILE *F, ir_graph *irg) {
1660 ir_graph *rem = current_ir_graph;
1661 ir_extblk **arr = ird_get_irg_link(irg);
1662 current_ir_graph = irg;
1664 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1665 ir_extblk *extbb = arr[i];
1666 ir_node *leader = get_extbb_leader(extbb);
1669 fprintf(F, "graph: { title: \"");
1670 PRINT_EXTBBID(leader);
1671 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1672 get_irn_node_nr(leader));
1674 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1675 ir_node * node = extbb->blks[j];
1676 if (is_Block(node)) {
1677 /* Dumps the block and all the nodes in the block, which are to
1678 be found in Block->link. */
1679 dump_whole_block(F, node);
1681 /* Nodes that are not in a Block. */
1683 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1684 dump_const_block_local(F, node);
1686 dump_ir_data_edges(F, node);
1692 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1693 dump_loop_nodes_into_graph(F, irg);
1695 current_ir_graph = rem;
1700 /*******************************************************************/
1701 /* Basic type and entity nodes and edges. */
1702 /*******************************************************************/
1704 /** dumps the edges between nodes and their type or entity attributes. */
1705 static void dump_node2type_edges(ir_node *n, void *env)
1710 switch (get_irn_opcode(n)) {
1712 /* @@@ some consts have an entity */
1715 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1716 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1719 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1722 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1725 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1728 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1731 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1739 static int print_type_info(FILE *F, ir_type *tp) {
1742 if (get_type_state(tp) == layout_undefined) {
1743 fprintf(F, "state: layout_undefined\n");
1745 fprintf(F, "state: layout_fixed,\n");
1747 if (get_type_mode(tp))
1748 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1749 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1754 static void print_typespecific_info(FILE *F, ir_type *tp) {
1755 switch (get_type_tpop_code(tp)) {
1758 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1765 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1766 fprintf(F, "params: %d\n", get_method_n_params(tp));
1767 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1775 case tpo_enumeration:
1789 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1790 switch (get_type_tpop_code(tp)) {
1793 if (peculiarity_existent == get_class_peculiarity(tp))
1794 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1796 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1800 fprintf (F, " " TYPE_METH_NODE_ATTR);
1811 case tpo_enumeration:
1825 int dump_type_node(FILE *F, ir_type *tp)
1829 fprintf (F, "node: {title: ");
1831 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1832 fprintf (F, " info1: \"");
1834 bad |= print_type_info(F, tp);
1835 print_typespecific_info(F, tp);
1837 dump_type_to_file(F, tp, dump_verbosity_max);
1839 fprintf (F, "\"\n");
1840 print_dbg_info(F, get_type_dbg_info(tp));
1841 print_typespecific_vcgattr(F, tp);
1848 #define X(a) case a: fprintf(F, #a); break
1849 void dump_entity_node(FILE *F, ir_entity *ent, int color)
1851 fprintf (F, "node: {title: \"");
1852 PRINT_ENTID(ent); fprintf(F, "\"");
1853 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1854 fprintf (F, "label: ");
1855 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1857 fprintf(F, "color:%d", color);
1859 fprintf (F, ENTITY_NODE_ATTR);
1860 fprintf (F, "\n info1: \"");
1862 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1865 print_dbg_info(F, get_entity_dbg_info(ent));
1870 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1873 ir_enum_const *ec = get_enumeration_const(tp, pos);
1874 ident *id = get_enumeration_nameid(ec);
1875 tarval *tv = get_enumeration_value(ec);
1878 tarval_snprintf(buf, sizeof(buf), tv);
1880 strncpy(buf, "<not set>", sizeof(buf));
1881 fprintf(F, "node: {title: \"");
1882 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1883 fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1884 fprintf(F, "label: ");
1885 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1886 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1889 /* dumps a type or entity and it's edges. */
1891 dump_type_info(type_or_ent *tore, void *env) {
1893 int i = 0; /* to shutup gcc */
1895 /* dump this type or entity */
1897 switch (get_kind(tore)) {
1900 ir_entity *ent = (ir_entity *)tore;
1903 dump_entity_node(F, ent, 0);
1905 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1906 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1907 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1908 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1909 if (is_Class_type(get_entity_owner(ent))) {
1910 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1911 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1913 /* attached subgraphs */
1914 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1915 if (is_atomic_entity(ent)) {
1916 value = get_atomic_ent_value(ent);
1918 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1919 /* DDMN(value); $$$ */
1920 dump_const_expression(F, value);
1923 if (is_compound_entity(ent)) {
1924 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1925 value = get_compound_ent_value(ent, i);
1927 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1928 dump_const_expression(F, value);
1929 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1931 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1932 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1933 get_compound_ent_value_member(ent, i), i);
1942 ir_type *tp = (ir_type *)tore;
1943 dump_type_node(F, tp);
1944 /* and now the edges */
1945 switch (get_type_tpop_code(tp)) {
1948 for (i=0; i < get_class_n_supertypes(tp); i++)
1949 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1950 for (i=0; i < get_class_n_members(tp); i++)
1951 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1955 for (i=0; i < get_struct_n_members(tp); i++)
1956 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1960 for (i = 0; i < get_method_n_params(tp); i++)
1961 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1962 for (i = 0; i < get_method_n_ress(tp); i++)
1963 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1967 for (i = 0; i < get_union_n_members(tp); i++)
1968 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1972 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1973 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1974 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1975 ir_node *upper = get_array_upper_bound(tp, i);
1976 ir_node *lower = get_array_lower_bound(tp, i);
1977 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1978 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1979 dump_const_expression(F, upper);
1980 dump_const_expression(F, lower);
1984 case tpo_enumeration:
1986 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1987 dump_enum_item(F, tp, i);
1988 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1993 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
2001 break; /* case k_type */
2004 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
2006 } /* switch kind_or_entity */
2009 typedef struct _h_env {
2014 /** For dumping class hierarchies.
2015 * Dumps a class type node and a superclass edge.
2016 * If env->dump_ent dumps entities of classes and overwrites edges.
2019 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
2022 int i = 0; /* to shutup gcc */
2024 /* dump this type or entity */
2025 switch (get_kind(tore)) {
2027 ir_entity *ent = (ir_entity *)tore;
2028 if (get_entity_owner(ent) == get_glob_type()) break;
2029 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
2030 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
2032 dump_entity_node(F, ent, 0);
2034 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
2035 for(i = 0; i < get_entity_n_overwrites(ent); i++)
2036 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
2038 } break; /* case k_entity */
2041 ir_type *tp = (ir_type *)tore;
2042 if (tp == get_glob_type()) break;
2043 switch (get_type_tpop_code(tp)) {
2045 dump_type_node(F, tp);
2046 /* and now the edges */
2047 for (i=0; i < get_class_n_supertypes(tp); i++)
2049 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2055 break; /* case k_type */
2058 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2060 } /* switch kind_or_entity */
2063 /*******************************************************************/
2064 /* dump analysis information that is expressed in graph terms. */
2065 /*******************************************************************/
2067 /* dump out edges */
2069 dump_out_edge(ir_node *n, void *env) {
2072 for (i = 0; i < get_irn_n_outs(n); i++) {
2073 assert(get_irn_out(n, i));
2074 fprintf (F, "edge: {sourcename: \"");
2076 fprintf (F, "\" targetname: \"");
2077 PRINT_NODEID(get_irn_out(n, i));
2078 fprintf (F, "\" color: red linestyle: dashed");
2084 dump_loop_label(FILE *F, ir_loop *loop) {
2085 fprintf (F, "loop %d, %d sons, %d nodes",
2086 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2089 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2090 fprintf (F, " info1: \"");
2091 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
2092 #if DEBUG_libfirm /* GL @@@ debug analyses */
2093 fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2099 dump_loop_node(FILE *F, ir_loop *loop) {
2100 fprintf (F, "node: {title: \"");
2102 fprintf (F, "\" label: \"");
2103 dump_loop_label(F, loop);
2105 dump_loop_info(F, loop);
2111 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2113 fprintf (F, "edge: {sourcename: \"");
2115 fprintf (F, "\" targetname: \"");
2116 PRINT_NODEID(get_loop_node(loop, i));
2117 fprintf (F, "\" color: green");
2122 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2124 fprintf (F, "edge: {sourcename: \"");
2126 fprintf (F, "\" targetname: \"");
2127 PRINT_LOOPID(get_loop_son(loop, i));
2128 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
2129 get_loop_element_pos(loop, get_loop_son(loop, i)));
2133 void dump_loops(FILE *F, ir_loop *loop) {
2135 /* dump this loop node */
2136 dump_loop_node(F, loop);
2138 /* dump edges to nodes in loop -- only if it is a real loop */
2139 if (get_loop_depth(loop) != 0) {
2140 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2141 dump_loop_node_edge(F, loop, i);
2144 for (i = 0; i < get_loop_n_sons(loop); i++) {
2145 dump_loops(F, get_loop_son(loop, i));
2146 dump_loop_son_edge(F, loop, i);
2151 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2152 ir_graph *rem = current_ir_graph;
2153 current_ir_graph = irg;
2155 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2157 current_ir_graph = rem;
2162 * dumps the VCG header
2164 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2173 if (!orientation) orientation = "bottom_to_top";
2177 "graph: { title: \"ir graph of %s\"\n"
2178 "display_edge_labels: %s\n"
2179 "layoutalgorithm: mindepth\n"
2180 "manhattan_edges: yes\n"
2181 "port_sharing: no\n"
2183 "classname 1: \"intrablock Data\"\n"
2184 "classname 2: \"Block\"\n"
2185 "classname 3: \"Entity type\"\n"
2186 "classname 4: \"Entity owner\"\n"
2187 "classname 5: \"Method Param\"\n"
2188 "classname 6: \"Method Res\"\n"
2189 "classname 7: \"Super\"\n"
2190 "classname 8: \"Union\"\n"
2191 "classname 9: \"Points-to\"\n"
2192 "classname 10: \"Array Element Type\"\n"
2193 "classname 11: \"Overwrites\"\n"
2194 "classname 12: \"Member\"\n"
2195 "classname 13: \"Control Flow\"\n"
2196 "classname 14: \"intrablock Memory\"\n"
2197 "classname 15: \"Dominators\"\n"
2198 "classname 16: \"interblock Data\"\n"
2199 "classname 17: \"interblock Memory\"\n"
2200 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2201 "classname 19: \"Postdominators\"\n"
2202 "infoname 1: \"Attribute\"\n"
2203 "infoname 2: \"Verification errors\"\n"
2204 "infoname 3: \"Debug info\"\n",
2205 name, label, orientation);
2207 /* don't use all, the range is too whith/black. */
2211 "colorentry 100: 0 0 0\n"
2212 "colorentry 101: 20 0 0\n"
2213 "colorentry 102: 40 0 0\n"
2214 "colorentry 103: 60 0 0\n"
2215 "colorentry 104: 80 0 0\n"
2216 "colorentry 105: 100 0 0\n"
2217 "colorentry 106: 120 0 0\n"
2218 "colorentry 107: 140 0 0\n"
2219 "colorentry 108: 150 0 0\n"
2220 "colorentry 109: 180 0 0\n"
2221 "colorentry 110: 200 0 0\n"
2222 "colorentry 111: 220 0 0\n"
2223 "colorentry 112: 240 0 0\n"
2224 "colorentry 113: 255 0 0\n"
2225 "colorentry 113: 255 20 20\n"
2226 "colorentry 114: 255 40 40\n"
2227 "colorentry 115: 255 60 60\n"
2228 "colorentry 116: 255 80 80\n"
2229 "colorentry 117: 255 100 100\n"
2230 "colorentry 118: 255 120 120\n"
2231 "colorentry 119: 255 140 140\n"
2232 "colorentry 120: 255 150 150\n"
2233 "colorentry 121: 255 180 180\n"
2234 "colorentry 122: 255 200 200\n"
2235 "colorentry 123: 255 220 220\n"
2236 "colorentry 124: 255 240 240\n"
2237 "colorentry 125: 255 250 250\n"
2240 fprintf (F, "\n"); /* a separator */
2246 * @param irg The graph to be dumped
2247 * @param suffix1 first filename suffix
2248 * @param suffix2 second filename suffix
2250 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2252 const char *nm = get_irg_dump_name(irg);
2253 int len = strlen(nm), i, j;
2254 char *fname; /* filename to put the vcg information in */
2256 if (!suffix1) suffix1 = "";
2257 if (!suffix2) suffix2 = "";
2259 /* open file for vcg graph */
2260 fname = xmalloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2262 /* strncpy (fname, nm, len); */ /* copy the filename */
2264 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2266 fname[j] = '@'; j++; fname[j] = '1'; j++;
2267 } else if (nm[i] == '@') {
2268 fname[j] = '@'; j++; fname[j] = '2'; j++;
2270 fname[j] = nm[i]; j++;
2274 strcat (fname, suffix1); /* append file suffix */
2275 strcat (fname, suffix2); /* append file suffix */
2276 strcat (fname, ".vcg"); /* append the .vcg suffix */
2278 /* vcg really expect only a <CR> at end of line, so
2279 * the "b"inary mode is what you mean (and even needed for Win32)
2281 F = fopen (fname, "wb"); /* open file for writing */
2283 panic("cannot open %s for writing (%m)", fname); /* not reached */
2293 * @param name prefix file name
2294 * @param suffix filename suffix
2296 FILE *vcg_open_name (const char *name, const char *suffix) {
2298 char *fname; /* filename to put the vcg information in */
2299 int i, j, len = strlen(name);
2301 if (!suffix) suffix = "";
2303 /** open file for vcg graph */
2304 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2305 /* strcpy (fname, name);*/ /* copy the filename */
2307 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2308 if (name[i] == '/') {
2309 fname[j] = '@'; j++; fname[j] = '1'; j++;
2310 } else if (name[i] == '@') {
2311 fname[j] = '@'; j++; fname[j] = '2'; j++;
2313 fname[j] = name[i]; j++;
2317 strcat (fname, suffix);
2318 strcat (fname, ".vcg"); /* append the .vcg suffix */
2320 /* vcg really expect only a <CR> at end of line, so
2321 * the "b"inary mode is what you mean (and even needed for Win32)
2323 F = fopen (fname, "wb"); /* open file for writing */
2325 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2333 * Dumps the vcg file footer
2335 static INLINE void dump_vcg_footer (FILE *F) {
2340 * close the vcg file
2342 void vcg_close (FILE *F) {
2343 dump_vcg_footer(F); /* print footer */
2344 fclose (F); /* close vcg file */
2347 /************************************************************************/
2348 /************************************************************************/
2349 /* Routines that dump all or parts of the firm representation to a file */
2350 /************************************************************************/
2351 /************************************************************************/
2353 /************************************************************************/
2354 /* Dump ir graphs, different formats and additional information. */
2355 /************************************************************************/
2357 /** Routine to dump a graph, blocks as conventional nodes. */
2359 dump_ir_graph (ir_graph *irg, const char *suffix )
2364 rem = current_ir_graph;
2366 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2368 current_ir_graph = irg;
2369 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2370 else suffix1 = "-pure";
2371 f = vcg_open(irg, suffix, suffix1);
2372 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2374 /* call the dump graph hook */
2375 if (dump_ir_graph_hook)
2376 if (dump_ir_graph_hook(f, irg))
2379 /* walk over the graph */
2380 /* dump_whole_node must be called in post visiting predecessors */
2381 ird_walk_graph(irg, NULL, dump_whole_node, f);
2383 /* dump the out edges in a separate walk */
2384 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2385 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2390 current_ir_graph = rem;
2393 /* Dump a firm graph without explicit block nodes. */
2394 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2400 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2403 if (get_interprocedural_view()) suffix1 = "-ip";
2405 f = vcg_open(irg, suffix, suffix1);
2406 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2408 construct_block_lists(irg);
2411 * If we are in the interprocedural view, we dump not
2412 * only the requested irg but also all irgs that can be reached
2415 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2416 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2418 dump_graph_from_list(f, get_irp_irg(i));
2426 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2427 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2434 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2437 if (get_irg_extblk_state(irg) != extblk_valid)
2440 if (get_interprocedural_view()) suffix1 = "-ip";
2443 ent = get_irg_entity(irg);
2445 F = vcg_open(irg, suffix, suffix1);
2446 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2448 construct_extblock_lists(irg);
2450 fprintf(F, "graph: { title: \"");
2452 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2453 get_ent_dump_name(ent));
2455 dump_graph_info(F, irg);
2456 print_dbg_info(F, get_entity_dbg_info(ent));
2458 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2459 ir_graph *irg = get_irp_irg(i);
2460 list_tuple *lists = ird_get_irg_link(irg);
2463 /* dump the extended blocks first */
2464 if (ARR_LEN(lists->extbb_list)) {
2465 ird_set_irg_link(irg, lists->extbb_list);
2466 dump_extblock_graph(F, irg);
2469 /* we may have blocks without extended blocks, bad for instance */
2470 if (ARR_LEN(lists->blk_list)) {
2471 ird_set_irg_link(irg, lists->blk_list);
2472 dump_block_graph(F, irg);
2475 DEL_ARR_F(lists->extbb_list);
2476 DEL_ARR_F(lists->blk_list);
2481 /* Close the vcg information for the irg */
2482 fprintf(F, "}\n\n");
2488 /* dumps a graph with type information */
2490 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2493 ir_graph *rem = current_ir_graph;
2495 int rem_dump_const_local;
2497 /* if a filter is set, dump only the irg's that match the filter */
2498 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2501 current_ir_graph = irg;
2502 rem_dump_const_local = dump_const_local;
2503 /* dumping types does not work with local nodes */
2504 dump_const_local = 0;
2506 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2507 else suffix1 = "-pure-wtypes";
2508 f = vcg_open(irg,suffix, suffix1);
2509 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2511 /* dump common ir graph */
2512 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2513 /* dump type info */
2514 type_walk_irg(irg, dump_type_info, NULL, f);
2515 inc_irg_visited(get_const_code_irg());
2516 /* dump edges from graph to type info */
2517 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2520 dump_const_local = rem_dump_const_local;
2521 current_ir_graph = rem;
2525 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2530 ir_graph *rem = current_ir_graph;
2531 int rem_dump_const_local;
2533 /* if a filter is set, dump only the irg's that match the filter */
2534 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2537 rem_dump_const_local = dump_const_local;
2538 /* dumping types does not work with local nodes */
2539 dump_const_local = 0;
2541 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2542 else suffix1 = "-wtypes";
2543 f = vcg_open(irg, suffix, suffix1);
2544 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2546 /* dump common blocked ir graph */
2547 construct_block_lists(irg);
2549 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2550 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2552 dump_graph_from_list(f, get_irp_irg(i));
2557 /* dump type info */
2558 current_ir_graph = irg;
2559 type_walk_irg(irg, dump_type_info, NULL, f);
2560 inc_irg_visited(get_const_code_irg());
2562 /* dump edges from graph to type info */
2563 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2566 dump_const_local = rem_dump_const_local;
2567 current_ir_graph = rem;
2570 /*---------------------------------------------------------------------*/
2571 /* The following routines dump a control flow graph. */
2572 /*---------------------------------------------------------------------*/
2575 dump_block_to_cfg(ir_node *block, void *env) {
2580 if (is_Block(block)) {
2581 /* This is a block. Dump a node for the block. */
2582 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2583 fprintf (F, "\" label: \"");
2584 if (block == get_irg_start_block(get_irn_irg(block)))
2585 fprintf(F, "Start ");
2586 if (block == get_irg_end_block(get_irn_irg(block)))
2589 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2590 PRINT_NODEID(block);
2592 fprintf(F, "info1:\"");
2594 /* the generic version. */
2595 dump_irnode_to_file(F, block);
2597 /* Check whether we have bad predecessors to color the block. */
2598 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2599 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2602 fprintf (F, "\""); /* closing quote of info */
2604 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2605 (block == get_irg_end_block(get_irn_irg(block))) )
2606 fprintf(F, " color:blue ");
2608 fprintf(F, " color:yellow ");
2611 /* Dump the edges */
2612 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2613 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2614 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2615 fprintf (F, "edge: { sourcename: \"");
2616 PRINT_NODEID(block);
2617 fprintf (F, "\" targetname: \"");
2619 fprintf (F, "\"}\n");
2622 /* Dump dominator/postdominator edge */
2623 if (dump_dominator_information_flag) {
2624 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2625 pred = get_Block_idom(block);
2626 fprintf (F, "edge: { sourcename: \"");
2627 PRINT_NODEID(block);
2628 fprintf (F, "\" targetname: \"");
2630 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2632 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2633 pred = get_Block_ipostdom(block);
2634 fprintf (F, "edge: { sourcename: \"");
2635 PRINT_NODEID(block);
2636 fprintf (F, "\" targetname: \"");
2638 fprintf (F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2645 dump_cfg (ir_graph *irg, const char *suffix)
2648 ir_graph *rem = current_ir_graph;
2649 int ipv = get_interprocedural_view();
2651 /* if a filter is set, dump only the irg's that match the filter */
2652 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2655 current_ir_graph = irg;
2657 f = vcg_open(irg, suffix, "-cfg");
2658 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2661 printf("Warning: dumping cfg not in interprocedural view!\n");
2662 set_interprocedural_view(0);
2665 /* walk over the blocks in the graph */
2666 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2667 dump_node(f, get_irg_bad(irg));
2669 set_interprocedural_view(ipv);
2671 current_ir_graph = rem;
2675 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2676 if (pset_find_ptr(mark_set, n)) return;
2678 pset_insert_ptr(mark_set, n);
2681 int i, start = is_Block(n) ? 0 : -1;
2682 dump_whole_node(n, F);
2683 for (i = start; i < get_irn_arity(n); ++i)
2684 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2687 /* Don't dump edges to nodes further out. These might be edges to
2688 nodes we already dumped, if there is a shorter path to these. */
2692 static int subgraph_counter = 0;
2693 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2696 pset *mark_set = pset_new_ptr(1);
2697 sprintf(buf, "-subg_%03d", subgraph_counter++);
2698 F = vcg_open(get_irn_irg(root), suffix, buf);
2699 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2700 descend_and_dump(F, root, depth, mark_set);
2706 static int weight_overall(int rec, int loop) {
2707 return 2*rec + loop;
2710 static int compute_color (int my, int max) {
2717 /* if small, scale to the full color range. */
2719 my = my * (n_colors/max);
2721 step = 1 + (max / n_colors);
2725 return base_color + n_colors - color;
2728 static int get_entity_color(ir_entity *ent) {
2729 ir_graph *irg = get_entity_irg(ent);
2733 int rec_depth = get_irg_recursion_depth(irg);
2734 int loop_depth = get_irg_loop_depth(irg);
2735 int overall_depth = weight_overall(rec_depth, loop_depth);
2737 int max_rec_depth = irp->max_callgraph_recursion_depth;
2738 int max_loop_depth = irp->max_callgraph_loop_depth;
2739 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2741 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2742 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2743 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2745 return my_overall_color;
2749 void dump_callgraph(const char *suffix) {
2752 int rem = edge_label;
2754 //ident *prefix = new_id_from_str("java/");
2756 F = vcg_open_name("Callgraph", suffix);
2757 dump_vcg_header(F, "Callgraph", NULL);
2759 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2760 ir_graph *irg = get_irp_irg(i);
2761 ir_entity *ent = get_irg_entity(irg);
2762 int j, n_callees = get_irg_n_callees(irg);
2764 /* Do not dump runtime system. */
2765 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2767 dump_entity_node(F, ent, get_entity_color(ent));
2768 for (j = 0; j < n_callees; ++j) {
2769 ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
2770 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2771 int be = is_irg_callee_backedge(irg, j);
2774 "label:\"recursion %d\" color:%d" :
2775 "label:\"calls %d\" color:%d";
2776 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2784 /* Dump all irgs in interprocedural view to a single file. */
2785 void dump_all_cg_block_graph(const char *suffix) {
2788 int rem_view = get_interprocedural_view();
2789 set_interprocedural_view(1);
2791 f = vcg_open_name("All_graphs", suffix);
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);
2812 /*---------------------------------------------------------------------*/
2813 /* the following routines dumps type information without any ir nodes. */
2814 /*---------------------------------------------------------------------*/
2817 dump_type_graph (ir_graph *irg, const char *suffix)
2821 rem = current_ir_graph;
2823 /* if a filter is set, dump only the irg's that match the filter */
2824 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2826 current_ir_graph = irg;
2828 f = vcg_open(irg, suffix, "-type");
2829 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2831 /* walk over the blocks in the graph */
2832 type_walk_irg(irg, dump_type_info, NULL, f);
2833 /* The walker for the const code can be called several times for the
2834 same (sub) expression. So that no nodes are dumped several times
2835 we decrease the visited flag of the corresponding graph after each
2836 walk. So now increase it finally. */
2837 inc_irg_visited(get_const_code_irg());
2840 current_ir_graph = rem;
2844 dump_all_types (const char *suffix)
2846 FILE *f = vcg_open_name("All_types", suffix);
2847 dump_vcg_header(f, "All_types", NULL);
2848 type_walk(dump_type_info, NULL, f);
2849 inc_irg_visited(get_const_code_irg());
2854 dump_class_hierarchy (int entities, const char *suffix)
2856 FILE *f = vcg_open_name("class_hierarchy", suffix);
2860 env.dump_ent = entities;
2861 dump_vcg_header(f, "class_hierarchy", NULL);
2862 type_walk(dump_class_hierarchy_node, NULL, &env);
2866 /*---------------------------------------------------------------------*/
2867 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2869 /* dump_ir_block_graph */
2871 /* dump_type_graph */
2872 /* dump_ir_graph_w_types */
2873 /*---------------------------------------------------------------------*/
2875 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2877 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2878 dmp_grph(get_irp_irg(i), suffix);
2882 /*--------------------------------------------------------------------------------*
2883 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2884 * packed together in one subgraph/box *
2885 *--------------------------------------------------------------------------------*/
2887 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2888 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2890 ir_loop *son = NULL;
2892 /* Dump a new loop node. */
2893 dump_loop_node(F, loop);
2895 /* Dump the loop elements. */
2897 for(i = 0; i < get_loop_n_elements(loop); i++) {
2898 le = get_loop_element(loop, i);
2900 if (get_kind(son) == k_ir_loop) {
2902 /* We are a loop son -> Recurse */
2904 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2905 fprintf(F, "\" }\n");
2906 fprintf (F, "edge: {sourcename: \"");
2908 fprintf (F, "\" targetname: \"");
2910 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2911 loop_node_started = 0;
2913 dump_loop_son_edge(F, loop, son_number++);
2914 dump_loops_standalone(F, son);
2915 } else if (get_kind(son) == k_ir_node) {
2916 /* We are a loop node -> Collect firm nodes */
2918 ir_node *n = le.node;
2921 if (!loop_node_started) {
2922 /* Start a new node which contains all firm nodes of the current loop */
2923 fprintf (F, "node: { title: \"");
2925 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2926 loop_node_started = 1;
2932 bad |= dump_node_label(F, n);
2933 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2934 if (has_backedges(n)) fprintf(F, "\t loop head!");
2935 } else { /* for callgraph loop tree */
2937 assert(get_kind(son) == k_ir_graph);
2939 /* We are a loop node -> Collect firm graphs */
2940 n = (ir_graph *)le.node;
2941 if (!loop_node_started) {
2942 /* Start a new node which contains all firm nodes of the current loop */
2943 fprintf (F, "node: { title: \"");
2945 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2946 loop_node_started = 1;
2951 fprintf (F, " %s", get_irg_dump_name(n));
2952 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2956 if (loop_node_started) {
2957 fprintf(F, "\" }\n");
2958 fprintf (F, "edge: {sourcename: \"");
2960 fprintf (F, "\" targetname: \"");
2962 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2963 loop_node_started = 0;
2967 void dump_loop_tree(ir_graph *irg, const char *suffix)
2970 ir_graph *rem = current_ir_graph;
2971 int el_rem = edge_label;
2974 /* if a filter is set, dump only the irg's that match the filter */
2975 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2977 current_ir_graph = irg;
2979 f = vcg_open(irg, suffix, "-looptree");
2980 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2982 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2986 edge_label = el_rem;
2987 current_ir_graph = rem;
2990 void dump_callgraph_loop_tree(const char *suffix) {
2992 F = vcg_open_name("Callgraph_looptree", suffix);
2993 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2994 dump_loops_standalone(F, irp->outermost_cg_loop);
2999 /*-----------------------------------------------------------------------------*/
3000 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
3001 /*-----------------------------------------------------------------------------*/
3003 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
3004 int i, son_number = 0, node_number = 0;
3006 if (dump_loop_information_flag) dump_loop_node(F, loop);
3008 for (i = 0; i < get_loop_n_elements(loop); i++) {
3009 loop_element le = get_loop_element(loop, i);
3010 if (*(le.kind) == k_ir_loop) {
3011 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
3013 collect_nodeloop(F, le.son, loopnodes);
3015 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
3016 eset_insert(loopnodes, le.node);
3021 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
3024 for(i = 0; i < get_loop_n_elements(loop); i++) {
3025 loop_element le = get_loop_element(loop, i);
3026 if (*(le.kind) == k_ir_loop) {
3028 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3030 if (is_Block(le.node)) start = 0; else start = -1;
3031 for (j = start; j < get_irn_arity(le.node); j++) {
3032 ir_node *pred = get_irn_n(le.node, j);
3033 if (!eset_contains(loopnodes, pred)) {
3034 eset_insert(extnodes, pred);
3035 if (!is_Block(pred)) {
3036 pred = get_nodes_block(pred);
3037 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3045 void dump_loop(ir_loop *l, const char *suffix) {
3048 eset *loopnodes = eset_create();
3049 eset *extnodes = eset_create();
3052 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3053 F = vcg_open_name (name, suffix);
3054 dump_vcg_header(F, name, NULL);
3056 /* collect all nodes to dump */
3057 collect_nodeloop(F, l, loopnodes);
3058 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3060 /* build block lists */
3061 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3062 set_irn_link(n, NULL);
3063 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3064 set_irn_link(n, NULL);
3065 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3067 b = get_nodes_block(n);
3068 set_irn_link(n, get_irn_link(b));
3071 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3073 b = get_nodes_block(n);
3074 set_irn_link(n, get_irn_link(b));
3078 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
3080 fprintf(F, "graph: { title: \"");
3082 fprintf(F, "\" label: \"");
3083 dump_node_opcode(F, b);
3084 fprintf (F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3085 fprintf(F, "\" status:clustered color:yellow\n");
3087 /* dump the blocks edges */
3088 dump_ir_data_edges(F, b);
3090 /* dump the nodes that go into the block */
3091 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3092 if (eset_contains(extnodes, n))
3093 overrule_nodecolor = ird_color_lightblue;
3095 overrule_nodecolor = ird_color_default;
3096 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3099 /* Close the vcg information for the block */
3101 dump_const_node_local(F, b);
3104 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
3106 fprintf(F, "graph: { title: \"");
3108 fprintf(F, "\" label: \"");
3109 dump_node_opcode(F, b);
3110 fprintf (F, " %ld:%d", get_irn_node_nr(b), get_irn_idx(b));
3111 fprintf(F, "\" status:clustered color:lightblue\n");
3113 /* dump the nodes that go into the block */
3114 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3115 if (!eset_contains(loopnodes, n))
3116 overrule_nodecolor = ird_color_lightblue;
3118 overrule_nodecolor = ird_color_default;
3119 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3122 /* Close the vcg information for the block */
3124 dump_const_node_local(F, b);
3128 eset_destroy(loopnodes);
3129 eset_destroy(extnodes);