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, 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, entity *E, 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, 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, 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, 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(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(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_type_tag:
683 fprintf(F, "SymC %s tag", get_type_name_ex(get_SymConst_type(n), &bad));
685 case symconst_type_size:
686 fprintf(F, "SymC %s size", get_type_name_ex(get_SymConst_type(n), &bad));
688 case symconst_type_align:
689 fprintf(F, "SymC %s align", get_type_name_ex(get_SymConst_type(n), &bad));
691 case symconst_enum_const:
692 fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
698 if (!get_interprocedural_view())
705 ir_node *pred = get_Proj_pred(n);
707 if (get_irn_opcode(pred) == iro_Cond
708 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
709 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
710 fprintf (F, "defProj");
718 if (get_interprocedural_view()) {
719 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
724 case iro_CallBegin: {
725 ir_node *addr = get_CallBegin_ptr(n);
727 if (get_irn_op(addr) == op_Sel)
728 ent = get_Sel_entity(addr);
729 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
730 ent = get_SymConst_entity(addr);
731 fprintf (F, "%s", get_irn_opname(n));
732 if (ent) fprintf (F, " %s", get_entity_name(ent));
736 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
739 fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
742 if (get_Conv_strict(n))
743 fprintf (F, "strict");
744 fprintf (F, "%s", get_irn_opname(n));
749 fprintf (F, "%s", get_irn_opname(n));
756 * Dump the mode of a node n to a file F.
757 * Ignore modes that are "always known".
759 static int dump_node_mode(FILE *F, ir_node *n)
762 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
765 /* call the dump_node operation if available */
767 return ops->dump_node(n, F, dump_node_mode_txt);
769 /* default implementation */
770 iro = get_irn_opcode(n);
782 ir_mode *mode = get_irn_mode(n);
784 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
785 (mode != mode_T || iro == iro_Proj))
786 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
794 * Dump the type of a node n to a file F if it's known.
796 static int dump_node_typeinfo(FILE *F, ir_node *n) {
799 if (opt_dump_analysed_type_info) {
800 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
801 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
802 ir_type *tp = get_irn_typeinfo_type(n);
803 if (tp != firm_none_type)
804 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
812 typedef struct _pns_lookup {
813 long nr; /**< the proj number */
814 const char *name; /**< the name of the Proj */
817 typedef struct _proj_lookup {
818 opcode code; /**< the opcode of the Proj predecessor */
819 unsigned num_data; /**< number of data entries */
820 const pns_lookup_t *data; /**< the data */
823 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
825 /** the lookup table for Proj(Start) names */
826 static const pns_lookup_t start_lut[] = {
827 #define X(a) { pn_Start_##a, #a }
837 /** the lookup table for Proj(Cond) names */
838 static const pns_lookup_t cond_lut[] = {
839 #define X(a) { pn_Cond_##a, #a }
845 /** the lookup table for Proj(Call) names */
846 static const pns_lookup_t call_lut[] = {
847 #define X(a) { pn_Call_##a, #a }
856 /** the lookup table for Proj(Quot) names */
857 static const pns_lookup_t quot_lut[] = {
858 #define X(a) { pn_Quot_##a, #a }
865 /** the lookup table for Proj(DivMod) names */
866 static const pns_lookup_t divmod_lut[] = {
867 #define X(a) { pn_DivMod_##a, #a }
875 /** the lookup table for Proj(Div) names */
876 static const pns_lookup_t div_lut[] = {
877 #define X(a) { pn_Div_##a, #a }
884 /** the lookup table for Proj(Mod) names */
885 static const pns_lookup_t mod_lut[] = {
886 #define X(a) { pn_Mod_##a, #a }
893 /** the lookup table for Proj(Load) names */
894 static const pns_lookup_t load_lut[] = {
895 #define X(a) { pn_Load_##a, #a }
902 /** the lookup table for Proj(Store) names */
903 static const pns_lookup_t store_lut[] = {
904 #define X(a) { pn_Store_##a, #a }
910 /** the lookup table for Proj(Alloc) names */
911 static const pns_lookup_t alloc_lut[] = {
912 #define X(a) { pn_Alloc_##a, #a }
919 /** the lookup table for Proj(CopyB) names */
920 static const pns_lookup_t copyb_lut[] = {
921 #define X(a) { pn_CopyB_##a, #a }
928 /** the lookup table for Proj(InstOf) names */
929 static const pns_lookup_t instof_lut[] = {
930 #define X(a) { pn_InstOf_##a, #a }
938 /** the lookup table for Proj(Raise) names */
939 static const pns_lookup_t raise_lut[] = {
940 #define X(a) { pn_Raise_##a, #a }
946 /** the lookup table for Proj(Bound) names */
947 static const pns_lookup_t bound_lut[] = {
948 #define X(a) { pn_Bound_##a, #a }
955 /** the Proj lookup table */
956 static const proj_lookup_t proj_lut[] = {
957 #define E(a) ARR_SIZE(a), a
958 { iro_Start, E(start_lut) },
959 { iro_Cond, E(cond_lut) },
960 { iro_Call, E(call_lut) },
961 { iro_Quot, E(quot_lut) },
962 { iro_DivMod, E(divmod_lut) },
963 { iro_Div, E(div_lut) },
964 { iro_Mod, E(mod_lut) },
965 { iro_Load, E(load_lut) },
966 { iro_Store, E(store_lut) },
967 { iro_Alloc, E(alloc_lut) },
968 { iro_CopyB, E(copyb_lut) },
969 { iro_InstOf, E(instof_lut) },
970 { iro_Raise, E(raise_lut) },
971 { iro_Bound, E(bound_lut) }
976 * Dump additional node attributes of some nodes to a file F.
979 dump_node_nodeattr(FILE *F, ir_node *n)
985 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
987 /* call the dump_node operation if available */
989 return ops->dump_node(n, F, dump_node_nodeattr_txt);
991 switch (get_irn_opcode(n)) {
993 if (0 && get_interprocedural_view()) {
994 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
999 pred = get_Proj_pred(n);
1000 proj_nr = get_Proj_proj(n);
1002 code = get_irn_opcode(pred);
1004 if (code == iro_Cmp)
1005 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
1006 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
1007 fprintf (F, "Arg %ld ", proj_nr);
1008 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
1009 fprintf (F, "%ld ", proj_nr);
1011 unsigned i, j, f = 0;
1013 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
1014 if (code == proj_lut[i].code) {
1015 for (j = 0; j < proj_lut[i].num_data; ++j) {
1016 if (proj_nr == proj_lut[i].data[j].nr) {
1017 fprintf (F, "%s ", proj_lut[i].data[j].name);
1026 fprintf (F, "%ld ", proj_nr);
1027 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1028 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1029 fprintf(F, "PRED ");
1030 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1031 fprintf(F, "PRED ");
1036 proj_nr = get_Filter_proj(n);
1037 if (! get_interprocedural_view()) {
1039 pred = get_Filter_pred(n);
1043 fprintf (F, "%ld ", proj_nr);
1046 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1049 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1052 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1055 fprintf (F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1066 #include "execution_frequency.h"
1067 #include "callgraph.h"
1069 void dump_node_ana_vals(FILE *F, ir_node *n) {
1071 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1072 get_irn_exec_freq(n),
1073 get_irg_method_execution_frequency(get_irn_irg(n)),
1074 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1075 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1080 /* Dumps a node label without the enclosing ". */
1081 int dump_node_label(FILE *F, ir_node *n) {
1084 bad |= dump_node_opcode(F, n);
1085 bad |= dump_node_mode(F, n);
1087 bad |= dump_node_typeinfo(F, n);
1088 bad |= dump_node_nodeattr(F, n);
1089 fprintf(F, "%ld", get_irn_node_nr(n));
1096 * Dumps the attributes of a node n into the file F.
1097 * Currently this is only the color of a node.
1099 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1104 print_vcg_color(F, ird_color_red);
1108 if (dump_node_vcgattr_hook)
1109 if (dump_node_vcgattr_hook(F, node, local))
1112 n = local ? local : node;
1114 if (overrule_nodecolor != ird_color_default) {
1115 print_vcg_color(F, overrule_nodecolor);
1119 switch (get_irn_opcode(n)) {
1126 print_vcg_color(F, ird_color_blue);
1129 if (is_Block_dead(n))
1130 print_vcg_color(F, ird_color_lightred);
1132 print_vcg_color(F, ird_color_lightyellow);
1135 print_vcg_color(F, ird_color_green);
1139 print_vcg_color(F, ird_color_gold);
1142 print_vcg_color(F, ird_color_orchid);
1148 print_vcg_color(F, ird_color_yellow);
1151 PRINT_DEFAULT_NODE_ATTR;
1155 /* Adds a new node info dumper callback. */
1156 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1158 hook_entry_t *info = xmalloc(sizeof(*info));
1160 info->hook._hook_node_info = cb;
1161 info->context = data;
1162 register_hook(hook_node_info, info);
1167 /* Remove a previously added info dumper callback. */
1168 void dump_remv_node_info_callback(void *handle)
1170 hook_entry_t *info = handle;
1171 unregister_hook(hook_node_info, info);
1176 * Dump the node information of a node n to a file F.
1178 static INLINE int dump_node_info(FILE *F, ir_node *n)
1181 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1183 fprintf (F, " info1: \"");
1184 bad = dump_irnode_to_file(F, n);
1185 /* call the dump_node operation if available */
1187 bad = ops->dump_node(n, F, dump_node_info_txt);
1189 /* allow additional info to be added */
1190 hook_node_info(F, n);
1197 * checks whether a node is "constant-like" ie can be treated "block-less"
1200 int is_constlike_node(ir_node *n) {
1201 ir_op *op = get_irn_op(n);
1202 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1206 /** outputs the predecessors of n, that are constants, local. I.e.,
1207 generates a copy of the constant predecessors for each node called with. */
1208 static void dump_const_node_local(FILE *F, ir_node *n) {
1210 if (!get_opt_dump_const_local()) return;
1212 /* Use visited flag to avoid outputting nodes twice.
1213 initialize it first. */
1214 for (i = 0; i < get_irn_arity(n); i++) {
1215 ir_node *con = get_irn_n(n, i);
1216 if (is_constlike_node(con)) {
1217 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1221 for (i = 0; i < get_irn_arity(n); i++) {
1222 ir_node *con = get_irn_n(n, i);
1223 if (is_constlike_node(con) && irn_not_visited(con)) {
1226 mark_irn_visited(con);
1227 /* Generate a new name for the node by appending the names of
1229 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1230 fprintf(F, " label: \"");
1231 bad |= dump_node_label(F, con);
1233 bad |= dump_node_info(F, con);
1234 dump_node_vcgattr(F, n, con, bad);
1240 /** If the block of an edge is a const_like node, dump it local with an edge */
1241 static void dump_const_block_local(FILE *F, ir_node *n) {
1244 if (!get_opt_dump_const_local()) return;
1246 blk = get_nodes_block(n);
1247 if (is_constlike_node(blk)) {
1250 /* Generate a new name for the node by appending the names of
1252 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1253 fprintf(F, "\" label: \"");
1254 bad |= dump_node_label(F, blk);
1256 bad |= dump_node_info(F, blk);
1257 dump_node_vcgattr(F, n, blk, bad);
1260 fprintf (F, "edge: { sourcename: \"");
1262 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1264 if (dump_edge_vcgattr_hook) {
1266 if (dump_edge_vcgattr_hook(F, n, -1)) {
1271 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1276 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1281 * prints the error message of a node to a file F as info2.
1283 static void INLINE print_node_error(FILE *F, const char *err_msg)
1288 fprintf (F, " info2: \"%s\"", err_msg);
1292 * prints debug messages of a node to file F as info3.
1294 static void print_dbg_info(FILE *F, dbg_info *dbg)
1298 if (__dbg_info_snprint) {
1300 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1301 fprintf (F, " info3: \"%s\"\n", buf);
1308 static void dump_node(FILE *F, ir_node *n)
1313 if (get_opt_dump_const_local() && is_constlike_node(n))
1316 /* dump this node */
1317 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1319 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1320 bad |= dump_node_label(F, n);
1321 dump_node_ana_vals(F, n);
1322 //dump_node_ana_info(F, n);
1324 bad |= dump_node_info(F, n);
1325 print_node_error(F, p);
1326 print_dbg_info(F, get_irn_dbg_info(n));
1327 dump_node_vcgattr(F, n, NULL, bad);
1329 dump_const_node_local(F, n);
1331 if(dump_node_edge_hook)
1332 dump_node_edge_hook(F, n);
1334 dump_irn_chi_term(F, n);
1335 dump_irn_state(F, n);
1339 /** dump the edge to the block this node belongs to */
1341 dump_ir_block_edge(FILE *F, ir_node *n) {
1342 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1343 if (is_no_Block(n)) {
1344 ir_node *block = get_nodes_block(n);
1346 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1347 dump_const_block_local(F, n);
1350 fprintf (F, "edge: { sourcename: \"");
1352 fprintf (F, "\" targetname: ");
1353 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1355 if (dump_edge_vcgattr_hook) {
1357 if (dump_edge_vcgattr_hook(F, n, -1)) {
1362 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1367 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1373 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1375 * do not use get_nodes_block() here, will fail
1376 * if the irg is not pinned.
1378 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1379 fprintf (F, INTRA_DATA_EDGE_ATTR);
1381 fprintf (F, INTER_DATA_EDGE_ATTR);
1385 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1387 * do not use get_nodes_block() here, will fail
1388 * if the irg is not pinned.
1390 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1391 fprintf (F, INTRA_MEM_EDGE_ATTR);
1393 fprintf (F, INTER_MEM_EDGE_ATTR);
1397 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1400 if (dump_edge_vcgattr_hook)
1401 if (dump_edge_vcgattr_hook(F, from, to))
1404 if (dump_backedge_information_flag && is_backedge(from, to))
1405 fprintf (F, BACK_EDGE_ATTR);
1407 switch (get_irn_opcode(from)) {
1409 fprintf (F, CF_EDGE_ATTR);
1411 case iro_Start: break;
1414 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1415 fprintf (F, CF_EDGE_ATTR);
1416 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1417 fprintf (F, INTER_MEM_EDGE_ATTR);
1421 if (is_Proj(from)) {
1422 if (get_irn_mode(from) == mode_M)
1423 print_mem_edge_vcgattr(F, from, to);
1424 else if (get_irn_mode(from) == mode_X)
1425 fprintf(F, CF_EDGE_ATTR);
1427 print_data_edge_vcgattr(F, from, to);
1429 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1430 print_mem_edge_vcgattr(F, from, to);
1431 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1432 fprintf (F, CF_EDGE_ATTR);
1434 print_data_edge_vcgattr(F, from, to);
1438 /* dump edges to our inputs */
1440 dump_ir_data_edges(FILE *F, ir_node *n) {
1442 unsigned long visited = get_irn_visited(n);
1444 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1447 for (i = 0; i < get_irn_arity(n); i++) {
1448 ir_node * pred = get_irn_n(n, i);
1451 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1452 continue; /* pred not dumped */
1454 if (dump_backedge_information_flag && is_backedge(n, i))
1455 fprintf (F, "backedge: {sourcename: \"");
1457 fprintf (F, "edge: {sourcename: \"");
1459 fprintf (F, "\" targetname: ");
1460 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1461 PRINT_CONSTID(n, pred);
1463 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1465 fprintf (F, " label: \"%d\" ", i);
1466 print_edge_vcgattr(F, n, i);
1471 /** Dumps a node and its edges but not the block edge
1474 dump_node_wo_blockedge (ir_node *n, void *env) {
1477 dump_ir_data_edges(F, n);
1480 /** Dumps a node and its edges.
1483 dump_whole_node (ir_node *n, void *env) {
1485 dump_node_wo_blockedge(n, env);
1486 if (!node_floats(n)) dump_ir_block_edge(F, n);
1490 dump_const_node(ir_node *n, void *env) {
1491 if (is_Block(n)) return;
1492 dump_node_wo_blockedge(n, env);
1495 /***********************************************************************/
1496 /* the following routines dump the nodes/irgs bracketed to graphs. */
1497 /***********************************************************************/
1499 /** Dumps a constant expression as entity initializer, array bound ...
1501 static void dump_const_expression(FILE *F, ir_node *value) {
1502 ir_graph *rem = current_ir_graph;
1503 int rem_dump_const_local = dump_const_local;
1504 dump_const_local = 0;
1505 current_ir_graph = get_const_code_irg();
1506 irg_walk(value, dump_const_node, NULL, F);
1507 /* Decrease visited flag so that we walk with the same flag for the next
1508 expression. This guarantees that we don't dump the same node twice,
1509 as for const expressions cse is performed to save memory. */
1510 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1511 current_ir_graph = rem;
1512 dump_const_local = rem_dump_const_local;
1515 /** Dump a block as graph containing its nodes.
1517 * Expects to find nodes belonging to the block as list in its
1519 * Dumps the edges of all nodes including itself. */
1521 dump_whole_block(FILE *F, ir_node *block) {
1523 dumper_colors color = ird_color_yellow;
1525 assert(is_Block(block));
1527 fprintf(F, "graph: { title: \"");
1528 PRINT_NODEID(block);
1529 fprintf(F, "\" label: \"");
1530 dump_node_label(F, block);
1532 if (get_opt_dump_abstvals())
1533 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1536 /* colorize blocks */
1537 if (! get_Block_matured(block))
1538 color = ird_color_red;
1539 if (is_Block_dead(block))
1540 color = ird_color_orange;
1542 fprintf(F, "\" status:clustered ");
1543 print_vcg_color(F, color);
1546 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1547 dump_node_info(F, block);
1548 print_dbg_info(F, get_irn_dbg_info(block));
1550 /* dump the blocks edges */
1551 dump_ir_data_edges(F, block);
1553 if (dump_block_edge_hook)
1554 dump_block_edge_hook(F, block);
1556 /* dump the nodes that go into the block */
1557 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1559 dump_ir_data_edges(F, node);
1562 /* Close the vcg information for the block */
1564 dump_const_node_local(F, block);
1566 dump_irn_chi_term(F, block);
1571 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1572 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1574 dump_block_graph(FILE *F, ir_graph *irg) {
1576 ir_graph *rem = current_ir_graph;
1577 ir_node **arr = ird_get_irg_link(irg);
1578 current_ir_graph = irg;
1580 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1581 ir_node * node = arr[i];
1582 if (is_Block(node)) {
1583 /* Dumps the block and all the nodes in the block, which are to
1584 be found in Block->link. */
1585 dump_whole_block(F, node);
1587 /* Nodes that are not in a Block. */
1589 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1590 dump_const_block_local(F, node);
1592 dump_ir_data_edges(F, node);
1596 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1597 dump_loop_nodes_into_graph(F, irg);
1599 current_ir_graph = rem;
1603 * Dump the info for an irg.
1604 * Parsed by XVCG but not shown. use yComp.
1606 static void dump_graph_info(FILE *F, ir_graph *irg) {
1607 fprintf(F, "info1: \"");
1608 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1612 /** Dumps an irg as a graph clustered by block nodes.
1613 * If interprocedural view edges can point to nodes out of this graph.
1615 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1616 entity *ent = get_irg_entity(irg);
1618 fprintf(F, "graph: { title: \"");
1620 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1621 get_ent_dump_name(ent));
1623 dump_graph_info(F, irg);
1624 print_dbg_info(F, get_entity_dbg_info(ent));
1626 dump_block_graph(F, irg);
1628 /* Close the vcg information for the irg */
1629 fprintf(F, "}\n\n");
1632 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1633 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1635 dump_extblock_graph(FILE *F, ir_graph *irg) {
1637 ir_graph *rem = current_ir_graph;
1638 ir_extblk **arr = ird_get_irg_link(irg);
1639 current_ir_graph = irg;
1641 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1642 ir_extblk *extbb = arr[i];
1643 ir_node *leader = get_extbb_leader(extbb);
1646 fprintf(F, "graph: { title: \"");
1647 PRINT_EXTBBID(leader);
1648 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1649 get_irn_node_nr(leader));
1651 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1652 ir_node * node = extbb->blks[j];
1653 if (is_Block(node)) {
1654 /* Dumps the block and all the nodes in the block, which are to
1655 be found in Block->link. */
1656 dump_whole_block(F, node);
1658 /* Nodes that are not in a Block. */
1660 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1661 dump_const_block_local(F, node);
1663 dump_ir_data_edges(F, node);
1669 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1670 dump_loop_nodes_into_graph(F, irg);
1672 current_ir_graph = rem;
1677 /*******************************************************************/
1678 /* Basic type and entity nodes and edges. */
1679 /*******************************************************************/
1681 /** dumps the edges between nodes and their type or entity attributes. */
1682 static void dump_node2type_edges(ir_node *n, void *env)
1687 switch (get_irn_opcode(n)) {
1689 /* @@@ some consts have an entity */
1692 if (SYMCONST_HAS_TYPE(get_SymConst_kind(n)))
1693 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1696 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1699 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1702 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1705 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1708 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1716 static int print_type_info(FILE *F, ir_type *tp) {
1719 if (get_type_state(tp) == layout_undefined) {
1720 fprintf(F, "state: layout_undefined\n");
1722 fprintf(F, "state: layout_fixed,\n");
1724 if (get_type_mode(tp))
1725 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1726 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1731 static void print_typespecific_info(FILE *F, ir_type *tp) {
1732 switch (get_type_tpop_code(tp)) {
1735 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1742 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1743 fprintf(F, "params: %d\n", get_method_n_params(tp));
1744 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1752 case tpo_enumeration:
1766 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1767 switch (get_type_tpop_code(tp)) {
1770 if (peculiarity_existent == get_class_peculiarity(tp))
1771 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1773 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1777 fprintf (F, " " TYPE_METH_NODE_ATTR);
1788 case tpo_enumeration:
1802 int dump_type_node(FILE *F, ir_type *tp)
1806 fprintf (F, "node: {title: ");
1808 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1809 fprintf (F, " info1: \"");
1811 bad |= print_type_info(F, tp);
1812 print_typespecific_info(F, tp);
1814 dump_type_to_file(F, tp, dump_verbosity_max);
1816 fprintf (F, "\"\n");
1817 print_dbg_info(F, get_type_dbg_info(tp));
1818 print_typespecific_vcgattr(F, tp);
1825 #define X(a) case a: fprintf(F, #a); break
1826 void dump_entity_node(FILE *F, entity *ent, int color)
1828 fprintf (F, "node: {title: \"");
1829 PRINT_ENTID(ent); fprintf(F, "\"");
1830 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1831 fprintf (F, "label: ");
1832 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1834 fprintf(F, "color:%d", color);
1836 fprintf (F, ENTITY_NODE_ATTR);
1837 fprintf (F, "\n info1: \"");
1839 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1842 print_dbg_info(F, get_entity_dbg_info(ent));
1847 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1850 ir_enum_const *ec = get_enumeration_const(tp, pos);
1851 ident *id = get_enumeration_nameid(ec);
1852 tarval *tv = get_enumeration_value(ec);
1855 tarval_snprintf(buf, sizeof(buf), tv);
1857 strncpy(buf, "<not set>", sizeof(buf));
1858 fprintf(F, "node: {title: \"");
1859 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1860 fprintf(F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1861 fprintf(F, "label: ");
1862 fprintf(F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1863 fprintf(F, "\n info1: \"value: %s\"}\n", buf);
1866 /* dumps a type or entity and it's edges. */
1868 dump_type_info(type_or_ent *tore, void *env) {
1870 int i = 0; /* to shutup gcc */
1872 /* dump this type or entity */
1874 switch (get_kind(tore)) {
1877 entity *ent = (entity *)tore;
1880 dump_entity_node(F, ent, 0);
1882 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1883 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1884 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1885 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1886 if (is_Class_type(get_entity_owner(ent))) {
1887 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1888 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1890 /* attached subgraphs */
1891 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1892 if (is_atomic_entity(ent)) {
1893 value = get_atomic_ent_value(ent);
1895 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1896 /* DDMN(value); $$$ */
1897 dump_const_expression(F, value);
1900 if (is_compound_entity(ent)) {
1901 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1902 value = get_compound_ent_value(ent, i);
1904 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1905 dump_const_expression(F, value);
1906 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1908 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1909 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1910 get_compound_ent_value_member(ent, i), i);
1919 ir_type *tp = (ir_type *)tore;
1920 dump_type_node(F, tp);
1921 /* and now the edges */
1922 switch (get_type_tpop_code(tp)) {
1925 for (i=0; i < get_class_n_supertypes(tp); i++)
1926 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1927 for (i=0; i < get_class_n_members(tp); i++)
1928 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1932 for (i=0; i < get_struct_n_members(tp); i++)
1933 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1937 for (i = 0; i < get_method_n_params(tp); i++)
1938 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1939 for (i = 0; i < get_method_n_ress(tp); i++)
1940 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1944 for (i = 0; i < get_union_n_members(tp); i++)
1945 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1949 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1950 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1951 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1952 ir_node *upper = get_array_upper_bound(tp, i);
1953 ir_node *lower = get_array_lower_bound(tp, i);
1954 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1955 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1956 dump_const_expression(F, upper);
1957 dump_const_expression(F, lower);
1961 case tpo_enumeration:
1963 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1964 dump_enum_item(F, tp, i);
1965 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1970 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1978 break; /* case k_type */
1981 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 entity *ent = (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);
2015 } break; /* case k_entity */
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++)
2026 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2032 break; /* case k_type */
2035 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2037 } /* switch kind_or_entity */
2040 /*******************************************************************/
2041 /* dump analysis information that is expressed in graph terms. */
2042 /*******************************************************************/
2044 /* dump out edges */
2046 dump_out_edge(ir_node *n, void *env) {
2049 for (i = 0; i < get_irn_n_outs(n); i++) {
2050 assert(get_irn_out(n, i));
2051 fprintf (F, "edge: {sourcename: \"");
2053 fprintf (F, "\" targetname: \"");
2054 PRINT_NODEID(get_irn_out(n, i));
2055 fprintf (F, "\" color: red linestyle: dashed");
2061 dump_loop_label(FILE *F, ir_loop *loop) {
2062 fprintf (F, "loop %d, %d sons, %d nodes",
2063 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2066 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2067 fprintf (F, " info1: \"");
2068 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
2069 #if DEBUG_libfirm /* GL @@@ debug analyses */
2070 fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2076 dump_loop_node(FILE *F, ir_loop *loop) {
2077 fprintf (F, "node: {title: \"");
2079 fprintf (F, "\" label: \"");
2080 dump_loop_label(F, loop);
2082 dump_loop_info(F, loop);
2088 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2090 fprintf (F, "edge: {sourcename: \"");
2092 fprintf (F, "\" targetname: \"");
2093 PRINT_NODEID(get_loop_node(loop, i));
2094 fprintf (F, "\" color: green");
2099 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2101 fprintf (F, "edge: {sourcename: \"");
2103 fprintf (F, "\" targetname: \"");
2104 PRINT_LOOPID(get_loop_son(loop, i));
2105 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
2106 get_loop_element_pos(loop, get_loop_son(loop, i)));
2110 void dump_loops(FILE *F, ir_loop *loop) {
2112 /* dump this loop node */
2113 dump_loop_node(F, loop);
2115 /* dump edges to nodes in loop -- only if it is a real loop */
2116 if (get_loop_depth(loop) != 0) {
2117 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2118 dump_loop_node_edge(F, loop, i);
2121 for (i = 0; i < get_loop_n_sons(loop); i++) {
2122 dump_loops(F, get_loop_son(loop, i));
2123 dump_loop_son_edge(F, loop, i);
2128 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2129 ir_graph *rem = current_ir_graph;
2130 current_ir_graph = irg;
2132 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2134 current_ir_graph = rem;
2139 * dumps the VCG header
2141 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2150 if (!orientation) orientation = "bottom_to_top";
2154 "graph: { title: \"ir graph of %s\"\n"
2155 "display_edge_labels: %s\n"
2156 "layoutalgorithm: mindepth\n"
2157 "manhattan_edges: yes\n"
2158 "port_sharing: no\n"
2160 "classname 1: \"intrablock Data\"\n"
2161 "classname 2: \"Block\"\n"
2162 "classname 3: \"Entity type\"\n"
2163 "classname 4: \"Entity owner\"\n"
2164 "classname 5: \"Method Param\"\n"
2165 "classname 6: \"Method Res\"\n"
2166 "classname 7: \"Super\"\n"
2167 "classname 8: \"Union\"\n"
2168 "classname 9: \"Points-to\"\n"
2169 "classname 10: \"Array Element Type\"\n"
2170 "classname 11: \"Overwrites\"\n"
2171 "classname 12: \"Member\"\n"
2172 "classname 13: \"Control Flow\"\n"
2173 "classname 14: \"intrablock Memory\"\n"
2174 "classname 15: \"Dominators\"\n"
2175 "classname 16: \"interblock Data\"\n"
2176 "classname 17: \"interblock Memory\"\n"
2177 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2178 "classname 19: \"Postdominators\"\n"
2179 "infoname 1: \"Attribute\"\n"
2180 "infoname 2: \"Verification errors\"\n"
2181 "infoname 3: \"Debug info\"\n",
2182 name, label, orientation);
2184 /* don't use all, the range is too whith/black. */
2188 "colorentry 100: 0 0 0\n"
2189 "colorentry 101: 20 0 0\n"
2190 "colorentry 102: 40 0 0\n"
2191 "colorentry 103: 60 0 0\n"
2192 "colorentry 104: 80 0 0\n"
2193 "colorentry 105: 100 0 0\n"
2194 "colorentry 106: 120 0 0\n"
2195 "colorentry 107: 140 0 0\n"
2196 "colorentry 108: 150 0 0\n"
2197 "colorentry 109: 180 0 0\n"
2198 "colorentry 110: 200 0 0\n"
2199 "colorentry 111: 220 0 0\n"
2200 "colorentry 112: 240 0 0\n"
2201 "colorentry 113: 255 0 0\n"
2202 "colorentry 113: 255 20 20\n"
2203 "colorentry 114: 255 40 40\n"
2204 "colorentry 115: 255 60 60\n"
2205 "colorentry 116: 255 80 80\n"
2206 "colorentry 117: 255 100 100\n"
2207 "colorentry 118: 255 120 120\n"
2208 "colorentry 119: 255 140 140\n"
2209 "colorentry 120: 255 150 150\n"
2210 "colorentry 121: 255 180 180\n"
2211 "colorentry 122: 255 200 200\n"
2212 "colorentry 123: 255 220 220\n"
2213 "colorentry 124: 255 240 240\n"
2214 "colorentry 125: 255 250 250\n"
2217 fprintf (F, "\n"); /* a separator */
2223 * @param irg The graph to be dumped
2224 * @param suffix1 first filename suffix
2225 * @param suffix2 second filename suffix
2227 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2229 const char *nm = get_irg_dump_name(irg);
2230 int len = strlen(nm), i, j;
2231 char *fname; /* filename to put the vcg information in */
2233 if (!suffix1) suffix1 = "";
2234 if (!suffix2) suffix2 = "";
2236 /* open file for vcg graph */
2237 fname = xmalloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2239 /* strncpy (fname, nm, len); */ /* copy the filename */
2241 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2243 fname[j] = '@'; j++; fname[j] = '1'; j++;
2244 } else if (nm[i] == '@') {
2245 fname[j] = '@'; j++; fname[j] = '2'; j++;
2247 fname[j] = nm[i]; j++;
2251 strcat (fname, suffix1); /* append file suffix */
2252 strcat (fname, suffix2); /* append file suffix */
2253 strcat (fname, ".vcg"); /* append the .vcg suffix */
2255 /* vcg really expect only a <CR> at end of line, so
2256 * the "b"inary mode is what you mean (and even needed for Win32)
2258 F = fopen (fname, "wb"); /* open file for writing */
2260 panic("cannot open %s for writing (%m)", fname); /* not reached */
2270 * @param name prefix file name
2271 * @param suffix filename suffix
2273 FILE *vcg_open_name (const char *name, const char *suffix) {
2275 char *fname; /* filename to put the vcg information in */
2276 int i, j, len = strlen(name);
2278 if (!suffix) suffix = "";
2280 /** open file for vcg graph */
2281 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2282 /* strcpy (fname, name);*/ /* copy the filename */
2284 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2285 if (name[i] == '/') {
2286 fname[j] = '@'; j++; fname[j] = '1'; j++;
2287 } else if (name[i] == '@') {
2288 fname[j] = '@'; j++; fname[j] = '2'; j++;
2290 fname[j] = name[i]; j++;
2294 strcat (fname, suffix);
2295 strcat (fname, ".vcg"); /* append the .vcg suffix */
2297 /* vcg really expect only a <CR> at end of line, so
2298 * the "b"inary mode is what you mean (and even needed for Win32)
2300 F = fopen (fname, "wb"); /* open file for writing */
2302 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2310 * Dumps the vcg file footer
2312 static INLINE void dump_vcg_footer (FILE *F) {
2317 * close the vcg file
2319 void vcg_close (FILE *F) {
2320 dump_vcg_footer(F); /* print footer */
2321 fclose (F); /* close vcg file */
2324 /************************************************************************/
2325 /************************************************************************/
2326 /* Routines that dump all or parts of the firm representation to a file */
2327 /************************************************************************/
2328 /************************************************************************/
2330 /************************************************************************/
2331 /* Dump ir graphs, different formats and additional information. */
2332 /************************************************************************/
2334 /** Routine to dump a graph, blocks as conventional nodes. */
2336 dump_ir_graph (ir_graph *irg, const char *suffix )
2341 rem = current_ir_graph;
2343 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2345 current_ir_graph = irg;
2346 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2347 else suffix1 = "-pure";
2348 f = vcg_open(irg, suffix, suffix1);
2349 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2351 /* call the dump graph hook */
2352 if (dump_ir_graph_hook)
2353 if (dump_ir_graph_hook(f, irg))
2356 /* walk over the graph */
2357 /* dump_whole_node must be called in post visiting predecessors */
2358 ird_walk_graph(irg, NULL, dump_whole_node, f);
2360 /* dump the out edges in a separate walk */
2361 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2362 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2367 current_ir_graph = rem;
2370 /* Dump a firm graph without explicit block nodes. */
2371 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2377 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2380 if (get_interprocedural_view()) suffix1 = "-ip";
2382 f = vcg_open(irg, suffix, suffix1);
2383 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2385 construct_block_lists(irg);
2388 * If we are in the interprocedural view, we dump not
2389 * only the requested irg but also all irgs that can be reached
2392 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2393 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2395 dump_graph_from_list(f, get_irp_irg(i));
2403 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2404 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2411 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2414 if (get_irg_extblk_state(irg) != extblk_valid)
2417 if (get_interprocedural_view()) suffix1 = "-ip";
2420 ent = get_irg_entity(irg);
2422 F = vcg_open(irg, suffix, suffix1);
2423 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2425 construct_extblock_lists(irg);
2427 fprintf(F, "graph: { title: \"");
2429 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2430 get_ent_dump_name(ent));
2432 dump_graph_info(F, irg);
2433 print_dbg_info(F, get_entity_dbg_info(ent));
2435 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2436 ir_graph *irg = get_irp_irg(i);
2437 list_tuple *lists = ird_get_irg_link(irg);
2440 /* dump the extended blocks first */
2441 if (ARR_LEN(lists->extbb_list)) {
2442 ird_set_irg_link(irg, lists->extbb_list);
2443 dump_extblock_graph(F, irg);
2446 /* we may have blocks without extended blocks, bad for instance */
2447 if (ARR_LEN(lists->blk_list)) {
2448 ird_set_irg_link(irg, lists->blk_list);
2449 dump_block_graph(F, irg);
2452 DEL_ARR_F(lists->extbb_list);
2453 DEL_ARR_F(lists->blk_list);
2458 /* Close the vcg information for the irg */
2459 fprintf(F, "}\n\n");
2465 /* dumps a graph with type information */
2467 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2470 ir_graph *rem = current_ir_graph;
2472 int rem_dump_const_local;
2474 /* if a filter is set, dump only the irg's that match the filter */
2475 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2478 current_ir_graph = irg;
2479 rem_dump_const_local = dump_const_local;
2480 /* dumping types does not work with local nodes */
2481 dump_const_local = 0;
2483 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2484 else suffix1 = "-pure-wtypes";
2485 f = vcg_open(irg,suffix, suffix1);
2486 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2488 /* dump common ir graph */
2489 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2490 /* dump type info */
2491 type_walk_irg(irg, dump_type_info, NULL, f);
2492 inc_irg_visited(get_const_code_irg());
2493 /* dump edges from graph to type info */
2494 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2497 dump_const_local = rem_dump_const_local;
2498 current_ir_graph = rem;
2502 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2507 ir_graph *rem = current_ir_graph;
2508 int rem_dump_const_local;
2510 /* if a filter is set, dump only the irg's that match the filter */
2511 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2514 rem_dump_const_local = dump_const_local;
2515 /* dumping types does not work with local nodes */
2516 dump_const_local = 0;
2518 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2519 else suffix1 = "-wtypes";
2520 f = vcg_open(irg, suffix, suffix1);
2521 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2523 /* dump common blocked ir graph */
2524 construct_block_lists(irg);
2526 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2527 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2529 dump_graph_from_list(f, get_irp_irg(i));
2534 /* dump type info */
2535 current_ir_graph = irg;
2536 type_walk_irg(irg, dump_type_info, NULL, f);
2537 inc_irg_visited(get_const_code_irg());
2539 /* dump edges from graph to type info */
2540 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2543 dump_const_local = rem_dump_const_local;
2544 current_ir_graph = rem;
2547 /*---------------------------------------------------------------------*/
2548 /* The following routines dump a control flow graph. */
2549 /*---------------------------------------------------------------------*/
2552 dump_block_to_cfg(ir_node *block, void *env) {
2557 if (is_Block(block)) {
2558 /* This is a block. Dump a node for the block. */
2559 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2560 fprintf (F, "\" label: \"");
2561 if (block == get_irg_start_block(get_irn_irg(block)))
2562 fprintf(F, "Start ");
2563 if (block == get_irg_end_block(get_irn_irg(block)))
2566 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2567 PRINT_NODEID(block);
2569 fprintf(F, "info1:\"");
2571 /* the generic version. */
2572 dump_irnode_to_file(F, block);
2574 /* Check whether we have bad predecessors to color the block. */
2575 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2576 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2579 fprintf (F, "\""); /* closing quote of info */
2581 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2582 (block == get_irg_end_block(get_irn_irg(block))) )
2583 fprintf(F, " color:blue ");
2585 fprintf(F, " color:yellow ");
2588 /* Dump the edges */
2589 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2590 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2591 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2592 fprintf (F, "edge: { sourcename: \"");
2593 PRINT_NODEID(block);
2594 fprintf (F, "\" targetname: \"");
2596 fprintf (F, "\"}\n");
2599 /* Dump dominator/postdominator edge */
2600 if (dump_dominator_information_flag) {
2601 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2602 pred = get_Block_idom(block);
2603 fprintf (F, "edge: { sourcename: \"");
2604 PRINT_NODEID(block);
2605 fprintf (F, "\" targetname: \"");
2607 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2609 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2610 pred = get_Block_ipostdom(block);
2611 fprintf (F, "edge: { sourcename: \"");
2612 PRINT_NODEID(block);
2613 fprintf (F, "\" targetname: \"");
2615 fprintf (F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2622 dump_cfg (ir_graph *irg, const char *suffix)
2625 ir_graph *rem = current_ir_graph;
2626 int ipv = get_interprocedural_view();
2628 /* if a filter is set, dump only the irg's that match the filter */
2629 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2632 current_ir_graph = irg;
2634 f = vcg_open(irg, suffix, "-cfg");
2635 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2638 printf("Warning: dumping cfg not in interprocedural view!\n");
2639 set_interprocedural_view(0);
2642 /* walk over the blocks in the graph */
2643 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2644 dump_node(f, get_irg_bad(irg));
2646 set_interprocedural_view(ipv);
2648 current_ir_graph = rem;
2652 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2653 if (pset_find_ptr(mark_set, n)) return;
2655 pset_insert_ptr(mark_set, n);
2658 int i, start = is_Block(n) ? 0 : -1;
2659 dump_whole_node(n, F);
2660 for (i = start; i < get_irn_arity(n); ++i)
2661 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2664 /* Don't dump edges to nodes further out. These might be edges to
2665 nodes we already dumped, if there is a shorter path to these. */
2669 static int subgraph_counter = 0;
2670 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2673 pset *mark_set = pset_new_ptr(1);
2674 sprintf(buf, "-subg_%03d", subgraph_counter++);
2675 F = vcg_open(get_irn_irg(root), suffix, buf);
2676 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2677 descend_and_dump(F, root, depth, mark_set);
2683 static int weight_overall(int rec, int loop) {
2684 return 2*rec + loop;
2687 static int compute_color (int my, int max) {
2694 /* if small, scale to the full color range. */
2696 my = my * (n_colors/max);
2698 step = 1 + (max / n_colors);
2702 return base_color + n_colors - color;
2705 static int get_entity_color(entity *ent) {
2706 ir_graph *irg = get_entity_irg(ent);
2710 int rec_depth = get_irg_recursion_depth(irg);
2711 int loop_depth = get_irg_loop_depth(irg);
2712 int overall_depth = weight_overall(rec_depth, loop_depth);
2714 int max_rec_depth = irp->max_callgraph_recursion_depth;
2715 int max_loop_depth = irp->max_callgraph_loop_depth;
2716 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2718 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2719 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2720 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2722 return my_overall_color;
2726 void dump_callgraph(const char *suffix) {
2729 int rem = edge_label;
2731 //ident *prefix = new_id_from_str("java/");
2733 F = vcg_open_name("Callgraph", suffix);
2734 dump_vcg_header(F, "Callgraph", NULL);
2736 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2737 ir_graph *irg = get_irp_irg(i);
2738 entity *ent = get_irg_entity(irg);
2739 int j, n_callees = get_irg_n_callees(irg);
2741 /* Do not dump runtime system. */
2742 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2744 dump_entity_node(F, ent, get_entity_color(ent));
2745 for (j = 0; j < n_callees; ++j) {
2746 entity *c = get_irg_entity(get_irg_callee(irg, j));
2747 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2748 int be = is_irg_callee_backedge(irg, j);
2751 "label:\"recursion %d\" color:%d" :
2752 "label:\"calls %d\" color:%d";
2753 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2761 /* Dump all irgs in interprocedural view to a single file. */
2762 void dump_all_cg_block_graph(const char *suffix) {
2765 int rem_view = get_interprocedural_view();
2766 set_interprocedural_view(1);
2768 f = vcg_open_name("All_graphs", suffix);
2769 dump_vcg_header(f, "All_graphs", NULL);
2771 /* collect nodes in all irgs reachable in call graph*/
2772 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2773 ird_set_irg_link(get_irp_irg(i), NULL);
2775 cg_walk(clear_link, collect_node, NULL);
2777 /* dump all graphs */
2778 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2779 current_ir_graph = get_irp_irg(i);
2780 assert(ird_get_irg_link(current_ir_graph));
2781 dump_graph_from_list(f, current_ir_graph);
2782 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2786 set_interprocedural_view(rem_view);
2789 /*---------------------------------------------------------------------*/
2790 /* the following routines dumps type information without any ir nodes. */
2791 /*---------------------------------------------------------------------*/
2794 dump_type_graph (ir_graph *irg, const char *suffix)
2798 rem = current_ir_graph;
2800 /* if a filter is set, dump only the irg's that match the filter */
2801 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2803 current_ir_graph = irg;
2805 f = vcg_open(irg, suffix, "-type");
2806 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2808 /* walk over the blocks in the graph */
2809 type_walk_irg(irg, dump_type_info, NULL, f);
2810 /* The walker for the const code can be called several times for the
2811 same (sub) expression. So that no nodes are dumped several times
2812 we decrease the visited flag of the corresponding graph after each
2813 walk. So now increase it finally. */
2814 inc_irg_visited(get_const_code_irg());
2817 current_ir_graph = rem;
2821 dump_all_types (const char *suffix)
2823 FILE *f = vcg_open_name("All_types", suffix);
2824 dump_vcg_header(f, "All_types", NULL);
2825 type_walk(dump_type_info, NULL, f);
2826 inc_irg_visited(get_const_code_irg());
2831 dump_class_hierarchy (int entities, const char *suffix)
2833 FILE *f = vcg_open_name("class_hierarchy", suffix);
2837 env.dump_ent = entities;
2838 dump_vcg_header(f, "class_hierarchy", NULL);
2839 type_walk(dump_class_hierarchy_node, NULL, &env);
2843 /*---------------------------------------------------------------------*/
2844 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2846 /* dump_ir_block_graph */
2848 /* dump_type_graph */
2849 /* dump_ir_graph_w_types */
2850 /*---------------------------------------------------------------------*/
2852 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2854 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2855 dmp_grph(get_irp_irg(i), suffix);
2859 /*--------------------------------------------------------------------------------*
2860 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2861 * packed together in one subgraph/box *
2862 *--------------------------------------------------------------------------------*/
2864 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2865 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2867 ir_loop *son = NULL;
2869 /* Dump a new loop node. */
2870 dump_loop_node(F, loop);
2872 /* Dump the loop elements. */
2874 for(i = 0; i < get_loop_n_elements(loop); i++) {
2875 le = get_loop_element(loop, i);
2877 if (get_kind(son) == k_ir_loop) {
2879 /* We are a loop son -> Recurse */
2881 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2882 fprintf(F, "\" }\n");
2883 fprintf (F, "edge: {sourcename: \"");
2885 fprintf (F, "\" targetname: \"");
2887 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2888 loop_node_started = 0;
2890 dump_loop_son_edge(F, loop, son_number++);
2891 dump_loops_standalone(F, son);
2892 } else if (get_kind(son) == k_ir_node) {
2893 /* We are a loop node -> Collect firm nodes */
2895 ir_node *n = le.node;
2898 if (!loop_node_started) {
2899 /* Start a new node which contains all firm nodes of the current loop */
2900 fprintf (F, "node: { title: \"");
2902 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2903 loop_node_started = 1;
2909 bad |= dump_node_label(F, n);
2910 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2911 if (has_backedges(n)) fprintf(F, "\t loop head!");
2912 } else { /* for callgraph loop tree */
2914 assert(get_kind(son) == k_ir_graph);
2916 /* We are a loop node -> Collect firm graphs */
2917 n = (ir_graph *)le.node;
2918 if (!loop_node_started) {
2919 /* Start a new node which contains all firm nodes of the current loop */
2920 fprintf (F, "node: { title: \"");
2922 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2923 loop_node_started = 1;
2928 fprintf (F, " %s", get_irg_dump_name(n));
2929 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2933 if (loop_node_started) {
2934 fprintf(F, "\" }\n");
2935 fprintf (F, "edge: {sourcename: \"");
2937 fprintf (F, "\" targetname: \"");
2939 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2940 loop_node_started = 0;
2944 void dump_loop_tree(ir_graph *irg, const char *suffix)
2947 ir_graph *rem = current_ir_graph;
2948 int el_rem = edge_label;
2951 /* if a filter is set, dump only the irg's that match the filter */
2952 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2954 current_ir_graph = irg;
2956 f = vcg_open(irg, suffix, "-looptree");
2957 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2959 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2963 edge_label = el_rem;
2964 current_ir_graph = rem;
2967 void dump_callgraph_loop_tree(const char *suffix) {
2969 F = vcg_open_name("Callgraph_looptree", suffix);
2970 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2971 dump_loops_standalone(F, irp->outermost_cg_loop);
2976 /*-----------------------------------------------------------------------------*/
2977 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2978 /*-----------------------------------------------------------------------------*/
2980 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2981 int i, son_number = 0, node_number = 0;
2983 if (dump_loop_information_flag) dump_loop_node(F, loop);
2985 for (i = 0; i < get_loop_n_elements(loop); i++) {
2986 loop_element le = get_loop_element(loop, i);
2987 if (*(le.kind) == k_ir_loop) {
2988 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2990 collect_nodeloop(F, le.son, loopnodes);
2992 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2993 eset_insert(loopnodes, le.node);
2998 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
3001 for(i = 0; i < get_loop_n_elements(loop); i++) {
3002 loop_element le = get_loop_element(loop, i);
3003 if (*(le.kind) == k_ir_loop) {
3005 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
3007 if (is_Block(le.node)) start = 0; else start = -1;
3008 for (j = start; j < get_irn_arity(le.node); j++) {
3009 ir_node *pred = get_irn_n(le.node, j);
3010 if (!eset_contains(loopnodes, pred)) {
3011 eset_insert(extnodes, pred);
3012 if (!is_Block(pred)) {
3013 pred = get_nodes_block(pred);
3014 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
3022 void dump_loop(ir_loop *l, const char *suffix) {
3025 eset *loopnodes = eset_create();
3026 eset *extnodes = eset_create();
3029 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3030 F = vcg_open_name (name, suffix);
3031 dump_vcg_header(F, name, NULL);
3033 /* collect all nodes to dump */
3034 collect_nodeloop(F, l, loopnodes);
3035 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3037 /* build block lists */
3038 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3039 set_irn_link(n, NULL);
3040 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3041 set_irn_link(n, NULL);
3042 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3044 b = get_nodes_block(n);
3045 set_irn_link(n, get_irn_link(b));
3048 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3050 b = get_nodes_block(n);
3051 set_irn_link(n, get_irn_link(b));
3055 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
3057 fprintf(F, "graph: { title: \"");
3059 fprintf(F, "\" label: \"");
3060 dump_node_opcode(F, b);
3061 fprintf (F, " %ld", get_irn_node_nr(b));
3062 fprintf(F, "\" status:clustered color:yellow\n");
3064 /* dump the blocks edges */
3065 dump_ir_data_edges(F, b);
3067 /* dump the nodes that go into the block */
3068 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3069 if (eset_contains(extnodes, n))
3070 overrule_nodecolor = ird_color_lightblue;
3072 overrule_nodecolor = ird_color_default;
3073 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3076 /* Close the vcg information for the block */
3078 dump_const_node_local(F, b);
3081 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
3083 fprintf(F, "graph: { title: \"");
3085 fprintf(F, "\" label: \"");
3086 dump_node_opcode(F, b);
3087 fprintf (F, " %ld", get_irn_node_nr(b));
3088 fprintf(F, "\" status:clustered color:lightblue\n");
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(loopnodes, n))
3093 overrule_nodecolor = ird_color_lightblue;
3095 overrule_nodecolor = ird_color_default;
3096 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3099 /* Close the vcg information for the block */
3101 dump_const_node_local(F, b);
3105 eset_destroy(loopnodes);
3106 eset_destroy(extnodes);