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-2003 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 /** The vcg node attribute hook. */
115 static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
116 /** The vcg node attribute hook. */
117 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
118 /** The vcg edge attribute hook. */
119 static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
121 /* set the ir graph hook */
122 void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
123 dump_ir_graph_hook = hook;
125 /* set the node attribute hook */
126 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
127 dump_node_vcgattr_hook = hook;
129 /* set the edge attribute hook */
130 void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
131 dump_edge_vcgattr_hook = hook;
134 int get_opt_dump_const_local(void) {
135 if (!dump_out_edge_flag && !dump_loop_information_flag)
136 return dump_const_local;
141 void only_dump_method_with_name(ident *name) {
142 dump_file_filter_id = name;
145 ident *get_dump_file_filter_ident(void) {
146 return dump_file_filter_id;
149 /** Returns non-zero if dump file filter is not set, or if it is a
151 int is_filtered_dump_name(ident *name) {
152 if (!dump_file_filter_id) return 1;
153 return id_is_prefix(dump_file_filter_id, name);
156 /* To turn off display of edge labels. Edge labels often cause xvcg to
157 abort with a segmentation fault. */
158 void turn_off_edge_labels(void) {
162 void dump_consts_local(int flag) {
163 dump_const_local = flag;
166 void dump_constant_entity_values(int flag) {
167 const_entities = flag;
170 void dump_keepalive_edges(int flag) {
171 dump_keepalive = flag;
174 int get_opt_dump_keepalive_edges(void) {
175 return dump_keepalive;
178 void dump_out_edges(int flag) {
179 dump_out_edge_flag = flag;
182 void dump_dominator_information(int flag) {
183 dump_dominator_information_flag = flag;
186 void dump_loop_information(int flag) {
187 dump_loop_information_flag = flag;
190 void dump_backedge_information(int flag) {
191 dump_backedge_information_flag = flag;
194 /* Dump the information of type field specified in ana/irtypeinfo.h.
195 * If the flag is set, the type name is output in [] in the node label,
196 * else it is output as info.
198 void set_opt_dump_analysed_type_info(int flag) {
199 opt_dump_analysed_type_info = flag;
202 void dump_pointer_values_to_info(int flag) {
203 opt_dump_pointer_values_to_info = flag;
206 void dump_ld_names(int flag) {
210 void dump_all_anchors(int flag) {
214 /* -------------- some extended helper functions ----------------- */
217 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
218 * in the later case, sets bad
220 const char *get_mode_name_ex(ir_mode *mode, int *bad)
223 return get_mode_name(mode);
229 * returns the name of a type or <ERROR> if mode is NOT a mode object.
230 * in the later case, sets bad
232 const char *get_type_name_ex(ir_type *tp, int *bad)
235 return get_type_name(tp);
241 * printf the VCG color
243 static void print_vcg_color(FILE *F, dumper_colors color) {
244 static const char *color_names[32] = {
245 "white", "blue", "red", "green",
246 "yellow", "magenta", "cyan", "darkgray",
247 "darkblue", "darkred", "darkgreen", "darkyellow",
248 "darkmagenta", "darkcyan", "gold", "lightgray",
249 "lightblue", "lightred", "lightgreen", "lightyellow",
250 "lightmagenta", "lightcyan", "lilac", "turquoise",
251 "aquamarine", "khaki", "purple", "yellowgreen",
252 "pink", "orange", "orchid", "black"
255 if (color != ird_color_default)
256 fprintf(F, "color:%s", color_names[color]);
260 * prints the edge from a type S to a type T with additional info fmt, ...
263 static void print_type_type_edge(FILE *F, ir_type *S, ir_type *T, const char *fmt, ...)
268 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
269 fprintf(F, " targetname: "); PRINT_TYPEID(T);
270 vfprintf(F, fmt, ap);
276 * prints the edge from a type T to an entity E with additional info fmt, ...
279 static void print_type_ent_edge(FILE *F, ir_type *T, entity *E, const char *fmt, ...)
284 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
285 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
286 vfprintf(F, fmt, ap);
292 * prints the edge from an entity E to an entity T with additional info fmt, ...
295 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
301 fprintf(F, "backedge: { sourcename: \"");
303 fprintf(F, "edge: { sourcename: \"");
305 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
306 vfprintf(F, fmt, ap);
312 * prints the edge from an entity E to a type T with additional info fmt, ...
315 static void print_ent_type_edge(FILE *F, entity *E, ir_type *T, const char *fmt, ...)
320 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
321 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
322 vfprintf(F, fmt, ap);
328 * prints the edge from a node N to a type T with additional info fmt, ...
331 static void print_node_type_edge(FILE *F, const ir_node *N, ir_type *T, const char *fmt, ...)
336 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
337 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
338 vfprintf(F, fmt, ap);
344 * prints the edge from a node N to an entity E with additional info fmt, ...
347 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
352 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
353 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
355 vfprintf(F, fmt, ap);
361 * prints the edge from an entity E to a node N with additional info fmt, ...
364 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
369 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
370 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
371 vfprintf(F, fmt, ap);
377 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
380 static void print_enum_item_edge(FILE *F, ir_type *E, int item, const char *fmt, ...)
385 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
386 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
387 vfprintf(F, fmt, ap);
392 /*-----------------------------------------------------------------*/
393 /* global and ahead declarations */
394 /*-----------------------------------------------------------------*/
396 static void dump_whole_node(ir_node *n, void *env);
397 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
399 /*-----------------------------------------------------------------*/
400 /* Helper functions. */
401 /*-----------------------------------------------------------------*/
404 * This map is used as a private link attr to be able to call dumper
405 * anywhere without destroying link fields.
407 static pmap *irdump_link_map = NULL;
409 /** NOT A STANDARD LIBFIRM INIT METHOD
411 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
412 * are off, we want to have as few interferences as possible. Therefore the
413 * initialization is performed lazily and not called from within init_firm.
415 * Creates the link attribute map. */
416 static void init_irdump(void) {
417 /* We need a new, empty map. */
418 if (irdump_link_map) pmap_destroy(irdump_link_map);
419 irdump_link_map = pmap_create();
420 if (!dump_file_filter_id)
421 dump_file_filter_id = new_id_from_str("");
424 * Returns the private link field.
426 static void *ird_get_irn_link(ir_node *n) {
428 if (!irdump_link_map) return NULL;
430 if (pmap_contains(irdump_link_map, (void *)n))
431 res = pmap_get(irdump_link_map, (void *)n);
436 * Sets the private link field.
438 static void ird_set_irn_link(ir_node *n, void *x) {
439 if (!irdump_link_map)
441 pmap_insert(irdump_link_map, (void *)n, x);
445 * Gets the private link field of an irg.
447 static void *ird_get_irg_link(ir_graph *irg) {
449 if (!irdump_link_map) return NULL;
451 if (pmap_contains(irdump_link_map, (void *)irg))
452 res = pmap_get(irdump_link_map, (void *)irg);
457 * Sets the private link field of an irg.
459 static void ird_set_irg_link(ir_graph *irg, void *x) {
460 if (!irdump_link_map) init_irdump();
461 pmap_insert(irdump_link_map, (void *)irg, x);
465 * Walker, clears the private link field.
467 static void clear_link(ir_node * node, void * env) {
468 ird_set_irn_link(node, NULL);
472 * If the entity has a ld_name, returns it if the dump_ld_name is set,
473 * else returns the name of the entity.
475 static const char *_get_ent_dump_name(entity *ent, int dump_ld_name) {
477 return "<NULL entity>";
479 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
480 if (ent->ld_name) return get_id_str(ent->ld_name);
482 return get_id_str(ent->name);
486 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
487 * else returns the name of the entity.
489 const char *get_ent_dump_name(entity *ent) {
490 return _get_ent_dump_name(ent, dump_ld_name);
493 /* Returns the name of an IRG. */
494 const char *get_irg_dump_name(ir_graph *irg) {
495 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
496 return _get_ent_dump_name(get_irg_entity(irg), 1);
500 * Returns non-zero if a node is in floating state.
502 static int node_floats(ir_node *n) {
503 return ((get_irn_pinned(n) == op_pin_state_floats) &&
504 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
508 * Walker that visits the anchors
510 static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
511 irg_walk_graph(irg, pre, post, env);
516 for (i = anchor_max - 1; i >= 0; --i) {
517 ir_node *n = irg->anchors[i];
520 /* reset the visit flag: will be increase in the walker */
521 set_irg_visited(irg, get_irg_visited(irg) - 1);
522 irg_walk(n, pre, post, env);
529 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
531 static void collect_node(ir_node * node, void *env) {
534 || get_irn_op(node) == op_Bad
535 || get_irn_op(node) == op_Unknown
536 || get_irn_op(node) == op_NoMem) {
537 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
538 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
539 ARR_APP1(ir_node *, arr, node);
540 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
542 ir_node * block = get_nodes_block(node);
545 /* this node is in a Bad block, so we must place it into the graph's list */
546 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
547 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
548 ARR_APP1(ir_node *, arr, node);
549 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
552 ird_set_irn_link(node, ird_get_irn_link(block));
553 ird_set_irn_link(block, node);
558 /** Construct lists to walk ir block-wise.
560 * Collects all blocks, nodes not op_pin_state_pinned,
561 * Bad, NoMem and Unknown into a flexible array in link field of
562 * irg they belong to. Sets the irg link field to NULL in all
563 * graphs not visited.
564 * Free the list with DEL_ARR_F().
566 static ir_node **construct_block_lists(ir_graph *irg) {
567 int i, rem_view = get_interprocedural_view();
568 ir_graph *rem = current_ir_graph;
569 current_ir_graph = irg;
571 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
572 ird_set_irg_link(get_irp_irg(i), NULL);
574 ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
576 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
577 set_interprocedural_view(0);
579 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
580 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
581 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
582 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
584 set_interprocedural_view(rem_view);
586 current_ir_graph = rem;
587 return ird_get_irg_link(irg);
590 typedef struct _list_tuple {
592 ir_extblk **extbb_list;
595 /** Construct lists to walk IR extended block-wise.
596 * Free the lists in the tuple with DEL_ARR_F().
597 * Sets the irg link field to NULL in all
598 * graphs not visited.
600 static list_tuple *construct_extblock_lists(ir_graph *irg) {
601 ir_node **blk_list = construct_block_lists(irg);
603 ir_graph *rem = current_ir_graph;
604 list_tuple *lists = xmalloc(sizeof(*lists));
606 current_ir_graph = irg;
608 lists->blk_list = NEW_ARR_F(ir_node *, 0);
609 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
611 inc_irg_block_visited(irg);
612 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
615 if (is_Block(blk_list[i])) {
616 ext = get_Block_extbb(blk_list[i]);
618 if (extbb_not_visited(ext)) {
619 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
620 mark_extbb_visited(ext);
624 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
628 current_ir_graph = rem;
629 ird_set_irg_link(irg, lists);
633 /*-----------------------------------------------------------------*/
634 /* Routines to dump information about a single ir node. */
635 /*-----------------------------------------------------------------*/
638 * dump the name of a node n to the File F.
640 int dump_node_opcode(FILE *F, ir_node *n)
643 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
645 /* call the dump_node operation if available */
647 return ops->dump_node(n, F, dump_node_opcode_txt);
649 /* implementation for default nodes */
650 switch (get_irn_opcode(n)) {
655 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
656 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
661 if (get_SymConst_kind(n) == symconst_addr_name) {
662 /* don't use get_SymConst_ptr_info as it mangles the name. */
663 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
664 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
665 assert(get_SymConst_entity(n));
666 assert(is_entity(get_SymConst_entity(n)));
667 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
669 assert(get_kind(get_SymConst_type(n)) == k_type);
670 assert(get_type_ident(get_SymConst_type(n)));
671 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
672 if (get_SymConst_kind(n) == symconst_type_tag)
680 if (!get_interprocedural_view())
687 ir_node *pred = get_Proj_pred(n);
689 if (get_irn_opcode(pred) == iro_Cond
690 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
691 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
692 fprintf (F, "defProj");
700 if (get_interprocedural_view()) {
701 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
706 case iro_CallBegin: {
707 ir_node *addr = get_CallBegin_ptr(n);
709 if (get_irn_op(addr) == op_Sel)
710 ent = get_Sel_entity(addr);
711 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
712 ent = get_SymConst_entity(addr);
713 fprintf (F, "%s", get_irn_opname(n));
714 if (ent) fprintf (F, " %s", get_entity_name(ent));
718 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
721 fprintf (F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
726 fprintf (F, "%s", get_irn_opname(n));
733 * Dump the mode of a node n to a file F.
734 * Ignore modes that are "always known".
736 static int dump_node_mode(FILE *F, ir_node *n)
739 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
742 /* call the dump_node operation if available */
744 return ops->dump_node(n, F, dump_node_mode_txt);
746 /* default implementation */
747 iro = get_irn_opcode(n);
759 ir_mode *mode = get_irn_mode(n);
761 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
762 (mode != mode_T || iro == iro_Proj))
763 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
771 * Dump the type of a node n to a file F if it's known.
773 static int dump_node_typeinfo(FILE *F, ir_node *n) {
776 if (opt_dump_analysed_type_info) {
777 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
778 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
779 ir_type *tp = get_irn_typeinfo_type(n);
780 if (tp != firm_none_type)
781 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
789 typedef struct _pns_lookup {
790 long nr; /**< the proj number */
791 const char *name; /**< the name of the Proj */
794 typedef struct _proj_lookup {
795 opcode code; /**< the opcode of the Proj predecessor */
796 unsigned num_data; /**< number of data entries */
797 const pns_lookup_t *data; /**< the data */
800 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
802 /** the lookup table for Proj(Start) names */
803 static const pns_lookup_t start_lut[] = {
804 #define X(a) { pn_Start_##a, #a }
813 /** the lookup table for Proj(Cond) names */
814 static const pns_lookup_t cond_lut[] = {
815 #define X(a) { pn_Cond_##a, #a }
821 /** the lookup table for Proj(Call) names */
822 static const pns_lookup_t call_lut[] = {
823 #define X(a) { pn_Call_##a, #a }
832 /** the lookup table for Proj(Quot) names */
833 static const pns_lookup_t quot_lut[] = {
834 #define X(a) { pn_Quot_##a, #a }
841 /** the lookup table for Proj(DivMod) names */
842 static const pns_lookup_t divmod_lut[] = {
843 #define X(a) { pn_DivMod_##a, #a }
851 /** the lookup table for Proj(Div) names */
852 static const pns_lookup_t div_lut[] = {
853 #define X(a) { pn_Div_##a, #a }
860 /** the lookup table for Proj(Mod) names */
861 static const pns_lookup_t mod_lut[] = {
862 #define X(a) { pn_Mod_##a, #a }
869 /** the lookup table for Proj(Load) names */
870 static const pns_lookup_t load_lut[] = {
871 #define X(a) { pn_Load_##a, #a }
878 /** the lookup table for Proj(Store) names */
879 static const pns_lookup_t store_lut[] = {
880 #define X(a) { pn_Store_##a, #a }
886 /** the lookup table for Proj(Alloc) names */
887 static const pns_lookup_t alloc_lut[] = {
888 #define X(a) { pn_Alloc_##a, #a }
895 /** the lookup table for Proj(CopyB) names */
896 static const pns_lookup_t copyb_lut[] = {
897 #define X(a) { pn_CopyB_##a, #a }
904 /** the lookup table for Proj(InstOf) names */
905 static const pns_lookup_t instof_lut[] = {
906 #define X(a) { pn_InstOf_##a, #a }
914 /** the lookup table for Proj(Raise) names */
915 static const pns_lookup_t raise_lut[] = {
916 #define X(a) { pn_Raise_##a, #a }
922 /** the lookup table for Proj(Bound) names */
923 static const pns_lookup_t bound_lut[] = {
924 #define X(a) { pn_Bound_##a, #a }
932 /** the Proj lookup table */
933 static const proj_lookup_t proj_lut[] = {
934 #define E(a) ARR_SIZE(a), a
935 { iro_Start, E(start_lut) },
936 { iro_Cond, E(cond_lut) },
937 { iro_Call, E(call_lut) },
938 { iro_Quot, E(quot_lut) },
939 { iro_DivMod, E(divmod_lut) },
940 { iro_Div, E(div_lut) },
941 { iro_Mod, E(mod_lut) },
942 { iro_Load, E(load_lut) },
943 { iro_Store, E(store_lut) },
944 { iro_Alloc, E(alloc_lut) },
945 { iro_CopyB, E(copyb_lut) },
946 { iro_InstOf, E(instof_lut) },
947 { iro_Raise, E(raise_lut) },
948 { iro_Bound, E(bound_lut) }
953 * Dump additional node attributes of some nodes to a file F.
956 dump_node_nodeattr(FILE *F, ir_node *n)
962 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
964 /* call the dump_node operation if available */
966 return ops->dump_node(n, F, dump_node_nodeattr_txt);
968 switch (get_irn_opcode(n)) {
970 if (0 && get_interprocedural_view()) {
971 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
976 pred = get_Proj_pred(n);
977 proj_nr = get_Proj_proj(n);
979 code = get_irn_opcode(pred);
982 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
983 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
984 fprintf (F, "Arg %ld ", proj_nr);
985 else if (code == iro_Cond && get_irn_mode(get_Cond_selector(pred)) != mode_b)
986 fprintf (F, "%ld ", proj_nr);
988 unsigned i, j, f = 0;
990 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
991 if (code == proj_lut[i].code) {
992 for (j = 0; j < proj_lut[i].num_data; ++j) {
993 if (proj_nr == proj_lut[i].data[j].nr) {
994 fprintf (F, "%s ", proj_lut[i].data[j].name);
1003 fprintf (F, "%ld ", proj_nr);
1004 if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
1005 if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
1006 fprintf(F, "PRED ");
1007 if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
1008 fprintf(F, "PRED ");
1013 proj_nr = get_Filter_proj(n);
1014 if (! get_interprocedural_view()) {
1016 pred = get_Filter_pred(n);
1020 fprintf (F, "%ld ", proj_nr);
1023 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
1026 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
1029 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
1032 fprintf (F, "(%s) ", get_type_name_ex(get_CopyB_type(n), &bad));
1043 #include "execution_frequency.h"
1044 #include "callgraph.h"
1046 void dump_node_ana_vals(FILE *F, ir_node *n) {
1048 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
1049 get_irn_exec_freq(n),
1050 get_irg_method_execution_frequency(get_irn_irg(n)),
1051 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
1052 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
1057 /* Dumps a node label without the enclosing ". */
1058 int dump_node_label(FILE *F, ir_node *n) {
1061 bad |= dump_node_opcode(F, n);
1062 bad |= dump_node_mode(F, n);
1064 bad |= dump_node_typeinfo(F, n);
1065 bad |= dump_node_nodeattr(F, n);
1066 fprintf(F, "%ld", get_irn_node_nr(n));
1073 * Dumps the attributes of a node n into the file F.
1074 * Currently this is only the color of a node.
1076 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
1081 print_vcg_color(F, ird_color_red);
1085 if (dump_node_vcgattr_hook)
1086 if (dump_node_vcgattr_hook(F, node, local))
1089 n = local ? local : node;
1091 if (overrule_nodecolor != ird_color_default) {
1092 print_vcg_color(F, overrule_nodecolor);
1096 switch (get_irn_opcode(n)) {
1103 print_vcg_color(F, ird_color_blue);
1106 if (is_Block_dead(n))
1107 print_vcg_color(F, ird_color_lightred);
1109 print_vcg_color(F, ird_color_lightyellow);
1112 print_vcg_color(F, ird_color_green);
1116 print_vcg_color(F, ird_color_gold);
1122 print_vcg_color(F, ird_color_yellow);
1125 PRINT_DEFAULT_NODE_ATTR;
1129 /* Adds a new node info dumper callback. */
1130 void *dump_add_node_info_callback(dump_node_info_cb_t *cb, void *data)
1132 hook_entry_t *info = xmalloc(sizeof(*info));
1134 info->hook._hook_node_info = cb;
1135 info->context = data;
1136 register_hook(hook_node_info, info);
1141 /* Remove a previously added info dumper callback. */
1142 void dump_remv_node_info_callback(void *handle)
1144 hook_entry_t *info = handle;
1145 unregister_hook(hook_node_info, info);
1150 * Dump the node information of a node n to a file F.
1152 static INLINE int dump_node_info(FILE *F, ir_node *n)
1155 const ir_op_ops *ops = get_op_ops(get_irn_op(n));
1157 fprintf (F, " info1: \"");
1158 bad = dump_irnode_to_file(F, n);
1159 /* call the dump_node operation if available */
1161 bad = ops->dump_node(n, F, dump_node_info_txt);
1163 /* allow additional info to be added */
1164 hook_node_info(F, n);
1171 * checks whether a node is "constant-like" ie can be treated "block-less"
1174 int is_constlike_node(ir_node *n) {
1175 ir_op *op = get_irn_op(n);
1176 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
1180 /** outputs the predecessors of n, that are constants, local. I.e.,
1181 generates a copy of the constant predecessors for each node called with. */
1182 static void dump_const_node_local(FILE *F, ir_node *n) {
1184 if (!get_opt_dump_const_local()) return;
1186 /* Use visited flag to avoid outputting nodes twice.
1187 initialize it first. */
1188 for (i = 0; i < get_irn_arity(n); i++) {
1189 ir_node *con = get_irn_n(n, i);
1190 if (is_constlike_node(con)) {
1191 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1195 for (i = 0; i < get_irn_arity(n); i++) {
1196 ir_node *con = get_irn_n(n, i);
1197 if (is_constlike_node(con) && irn_not_visited(con)) {
1200 mark_irn_visited(con);
1201 /* Generate a new name for the node by appending the names of
1203 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1204 fprintf(F, " label: \"");
1205 bad |= dump_node_label(F, con);
1207 bad |= dump_node_info(F, con);
1208 dump_node_vcgattr(F, n, con, bad);
1214 /** If the block of an edge is a const_like node, dump it local with an edge */
1215 static void dump_const_block_local(FILE *F, ir_node *n) {
1218 if (!get_opt_dump_const_local()) return;
1220 blk = get_nodes_block(n);
1221 if (is_constlike_node(blk)) {
1224 /* Generate a new name for the node by appending the names of
1226 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1227 fprintf(F, "\" label: \"");
1228 bad |= dump_node_label(F, blk);
1230 bad |= dump_node_info(F, blk);
1231 dump_node_vcgattr(F, n, blk, bad);
1234 fprintf (F, "edge: { sourcename: \"");
1236 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1238 if (dump_edge_vcgattr_hook) {
1240 if (dump_edge_vcgattr_hook(F, n, -1)) {
1245 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1250 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1255 * prints the error message of a node to a file F as info2.
1257 static void INLINE print_node_error(FILE *F, const char *err_msg)
1262 fprintf (F, " info2: \"%s\"", err_msg);
1266 * prints debug messages of a node to file F as info3.
1268 static void print_dbg_info(FILE *F, dbg_info *dbg)
1272 if (__dbg_info_snprint) {
1274 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1275 fprintf (F, " info3: \"%s\"\n", buf);
1282 static void dump_node(FILE *F, ir_node *n)
1287 if (get_opt_dump_const_local() && is_constlike_node(n))
1290 /* dump this node */
1291 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1293 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1294 bad |= dump_node_label(F, n);
1295 dump_node_ana_vals(F, n);
1296 //dump_node_ana_info(F, n);
1298 bad |= dump_node_info(F, n);
1299 print_node_error(F, p);
1300 print_dbg_info(F, get_irn_dbg_info(n));
1301 dump_node_vcgattr(F, n, NULL, bad);
1303 dump_const_node_local(F, n);
1305 if(dump_node_edge_hook)
1306 dump_node_edge_hook(F, n);
1308 dump_irn_chi_term(F, n);
1309 dump_irn_state(F, n);
1313 /** dump the edge to the block this node belongs to */
1315 dump_ir_block_edge(FILE *F, ir_node *n) {
1316 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1317 if (is_no_Block(n)) {
1318 ir_node *block = get_nodes_block(n);
1320 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1321 dump_const_block_local(F, n);
1324 fprintf (F, "edge: { sourcename: \"");
1326 fprintf (F, "\" targetname: ");
1327 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1329 if (dump_edge_vcgattr_hook) {
1331 if (dump_edge_vcgattr_hook(F, n, -1)) {
1336 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1341 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1347 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1349 * do not use get_nodes_block() here, will fail
1350 * if the irg is not pinned.
1352 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1353 fprintf (F, INTRA_DATA_EDGE_ATTR);
1355 fprintf (F, INTER_DATA_EDGE_ATTR);
1359 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1361 * do not use get_nodes_block() here, will fail
1362 * if the irg is not pinned.
1364 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1365 fprintf (F, INTRA_MEM_EDGE_ATTR);
1367 fprintf (F, INTER_MEM_EDGE_ATTR);
1371 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1374 if (dump_edge_vcgattr_hook)
1375 if (dump_edge_vcgattr_hook(F, from, to))
1378 if (dump_backedge_information_flag && is_backedge(from, to))
1379 fprintf (F, BACK_EDGE_ATTR);
1381 switch (get_irn_opcode(from)) {
1383 fprintf (F, CF_EDGE_ATTR);
1385 case iro_Start: break;
1388 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1389 fprintf (F, CF_EDGE_ATTR);
1390 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1391 fprintf (F, INTER_MEM_EDGE_ATTR);
1395 if (is_Proj(from)) {
1396 if (get_irn_mode(from) == mode_M)
1397 print_mem_edge_vcgattr(F, from, to);
1398 else if (get_irn_mode(from) == mode_X)
1399 fprintf(F, CF_EDGE_ATTR);
1401 print_data_edge_vcgattr(F, from, to);
1403 else if (get_irn_mode(get_irn_n(from, to)) == mode_M)
1404 print_mem_edge_vcgattr(F, from, to);
1405 else if (get_irn_mode(get_irn_n(from, to)) == mode_X)
1406 fprintf (F, CF_EDGE_ATTR);
1408 print_data_edge_vcgattr(F, from, to);
1412 /* dump edges to our inputs */
1414 dump_ir_data_edges(FILE *F, ir_node *n) {
1416 unsigned long visited = get_irn_visited(n);
1418 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1421 for (i = 0; i < get_irn_arity(n); i++) {
1422 ir_node * pred = get_irn_n(n, i);
1425 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1426 continue; /* pred not dumped */
1428 if (dump_backedge_information_flag && is_backedge(n, i))
1429 fprintf (F, "backedge: {sourcename: \"");
1431 fprintf (F, "edge: {sourcename: \"");
1433 fprintf (F, "\" targetname: ");
1434 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1435 PRINT_CONSTID(n, pred);
1437 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1439 fprintf (F, " label: \"%d\" ", i);
1440 print_edge_vcgattr(F, n, i);
1445 /** Dumps a node and its edges but not the block edge
1448 dump_node_wo_blockedge (ir_node *n, void *env) {
1451 dump_ir_data_edges(F, n);
1454 /** Dumps a node and its edges.
1457 dump_whole_node (ir_node *n, void *env) {
1459 dump_node_wo_blockedge(n, env);
1460 if (!node_floats(n)) dump_ir_block_edge(F, n);
1464 dump_const_node(ir_node *n, void *env) {
1465 if (is_Block(n)) return;
1466 dump_node_wo_blockedge(n, env);
1469 /***********************************************************************/
1470 /* the following routines dump the nodes/irgs bracketed to graphs. */
1471 /***********************************************************************/
1473 /** Dumps a constant expression as entity initializer, array bound ...
1475 static void dump_const_expression(FILE *F, ir_node *value) {
1476 ir_graph *rem = current_ir_graph;
1477 int rem_dump_const_local = dump_const_local;
1478 dump_const_local = 0;
1479 current_ir_graph = get_const_code_irg();
1480 irg_walk(value, dump_const_node, NULL, F);
1481 /* Decrease visited flag so that we walk with the same flag for the next
1482 expression. This guarantees that we don't dump the same node twice,
1483 as for const expressions cse is performed to save memory. */
1484 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1485 current_ir_graph = rem;
1486 dump_const_local = rem_dump_const_local;
1489 /** Dump a block as graph containing its nodes.
1491 * Expects to find nodes belonging to the block as list in its
1493 * Dumps the edges of all nodes including itself. */
1495 dump_whole_block(FILE *F, ir_node *block) {
1497 dumper_colors color = ird_color_yellow;
1499 assert(is_Block(block));
1501 fprintf(F, "graph: { title: \"");
1502 PRINT_NODEID(block);
1503 fprintf(F, "\" label: \"");
1504 dump_node_label(F, block);
1506 if (get_opt_dump_abstvals())
1507 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1510 /* colorize blocks */
1511 if (! get_Block_matured(block))
1512 color = ird_color_red;
1513 if (is_Block_dead(block))
1514 color = ird_color_orange;
1516 fprintf(F, "\" status:clustered ");
1517 print_vcg_color(F, color);
1520 /* yComp can show attributes for blocks, XVCG parses but ignores them */
1521 dump_node_info(F, block);
1522 print_dbg_info(F, get_irn_dbg_info(block));
1524 /* dump the blocks edges */
1525 dump_ir_data_edges(F, block);
1527 /* dump the nodes that go into the block */
1528 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1530 dump_ir_data_edges(F, node);
1533 /* Close the vcg information for the block */
1535 dump_const_node_local(F, block);
1537 dump_irn_chi_term(F, block);
1542 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1543 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1545 dump_block_graph(FILE *F, ir_graph *irg) {
1547 ir_graph *rem = current_ir_graph;
1548 ir_node **arr = ird_get_irg_link(irg);
1549 current_ir_graph = irg;
1551 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1552 ir_node * node = arr[i];
1553 if (is_Block(node)) {
1554 /* Dumps the block and all the nodes in the block, which are to
1555 be found in Block->link. */
1556 dump_whole_block(F, node);
1558 /* Nodes that are not in a Block. */
1560 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1561 dump_const_block_local(F, node);
1563 dump_ir_data_edges(F, node);
1567 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1568 dump_loop_nodes_into_graph(F, irg);
1570 current_ir_graph = rem;
1574 * Dump the info for an irg.
1575 * Parsed by XVCG but not shown. use yComp.
1577 static void dump_graph_info(FILE *F, ir_graph *irg) {
1578 fprintf(F, "info1: \"");
1579 dump_entity_to_file(F, get_irg_entity(irg), dump_verbosity_entattrs | dump_verbosity_entconsts);
1583 /** Dumps an irg as a graph clustered by block nodes.
1584 * If interprocedural view edges can point to nodes out of this graph.
1586 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1587 entity *ent = get_irg_entity(irg);
1589 fprintf(F, "graph: { title: \"");
1591 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1592 get_ent_dump_name(ent));
1594 dump_graph_info(F, irg);
1595 print_dbg_info(F, get_entity_dbg_info(ent));
1597 dump_block_graph(F, irg);
1599 /* Close the vcg information for the irg */
1600 fprintf(F, "}\n\n");
1603 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1604 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1606 dump_extblock_graph(FILE *F, ir_graph *irg) {
1608 ir_graph *rem = current_ir_graph;
1609 ir_extblk **arr = ird_get_irg_link(irg);
1610 current_ir_graph = irg;
1612 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1613 ir_extblk *extbb = arr[i];
1614 ir_node *leader = get_extbb_leader(extbb);
1617 fprintf(F, "graph: { title: \"");
1618 PRINT_EXTBBID(leader);
1619 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1620 get_irn_node_nr(leader));
1622 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1623 ir_node * node = extbb->blks[j];
1624 if (is_Block(node)) {
1625 /* Dumps the block and all the nodes in the block, which are to
1626 be found in Block->link. */
1627 dump_whole_block(F, node);
1629 /* Nodes that are not in a Block. */
1631 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1632 dump_const_block_local(F, node);
1634 dump_ir_data_edges(F, node);
1640 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1641 dump_loop_nodes_into_graph(F, irg);
1643 current_ir_graph = rem;
1648 /*******************************************************************/
1649 /* Basic type and entity nodes and edges. */
1650 /*******************************************************************/
1652 /** dumps the edges between nodes and their type or entity attributes. */
1653 static void dump_node2type_edges(ir_node *n, void *env)
1658 switch (get_irn_opcode(n)) {
1660 /* @@@ some consts have an entity */
1663 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1664 || (get_SymConst_kind(n) ==symconst_size))
1666 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1670 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1673 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1676 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1679 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1682 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1690 static int print_type_info(FILE *F, ir_type *tp) {
1693 if (get_type_state(tp) == layout_undefined) {
1694 fprintf(F, "state: layout_undefined\n");
1696 fprintf(F, "state: layout_fixed,\n");
1698 if (get_type_mode(tp))
1699 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1700 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1705 static void print_typespecific_info(FILE *F, ir_type *tp) {
1706 switch (get_type_tpop_code(tp)) {
1709 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1716 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1717 fprintf(F, "params: %d\n", get_method_n_params(tp));
1718 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1726 case tpo_enumeration:
1740 static void print_typespecific_vcgattr(FILE *F, ir_type *tp) {
1741 switch (get_type_tpop_code(tp)) {
1744 if (peculiarity_existent == get_class_peculiarity(tp))
1745 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1747 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1751 fprintf (F, " " TYPE_METH_NODE_ATTR);
1762 case tpo_enumeration:
1776 int dump_type_node(FILE *F, ir_type *tp)
1780 fprintf (F, "node: {title: ");
1782 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1783 fprintf (F, " info1: \"");
1785 bad |= print_type_info(F, tp);
1786 print_typespecific_info(F, tp);
1788 dump_type_to_file(F, tp, dump_verbosity_max);
1790 fprintf (F, "\"\n");
1791 print_dbg_info(F, get_type_dbg_info(tp));
1792 print_typespecific_vcgattr(F, tp);
1799 #define X(a) case a: fprintf(F, #a); break
1800 void dump_entity_node(FILE *F, entity *ent, int color)
1802 fprintf (F, "node: {title: \"");
1803 PRINT_ENTID(ent); fprintf(F, "\"");
1804 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1805 fprintf (F, "label: ");
1806 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1808 fprintf(F, "color:%d", color);
1810 fprintf (F, ENTITY_NODE_ATTR);
1811 fprintf (F, "\n info1: \"");
1813 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1816 print_dbg_info(F, get_entity_dbg_info(ent));
1821 static void dump_enum_item(FILE *F, ir_type *tp, int pos)
1824 ident *id = get_enumeration_nameid(tp, pos);
1825 tarval *tv = get_enumeration_enum(tp, pos);
1827 tarval_snprintf(buf, sizeof(buf), tv);
1828 fprintf (F, "node: {title: \"");
1829 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1830 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1831 fprintf (F, "label: ");
1832 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1833 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1836 /* dumps a type or entity and it's edges. */
1838 dump_type_info(type_or_ent *tore, void *env) {
1840 int i = 0; /* to shutup gcc */
1842 /* dump this type or entity */
1844 switch (get_kind(tore)) {
1847 entity *ent = (entity *)tore;
1850 dump_entity_node(F, ent, 0);
1852 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1853 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1854 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1855 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1856 if (is_Class_type(get_entity_owner(ent))) {
1857 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1858 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1860 /* attached subgraphs */
1861 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1862 if (is_atomic_entity(ent)) {
1863 value = get_atomic_ent_value(ent);
1865 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1866 /* DDMN(value); $$$ */
1867 dump_const_expression(F, value);
1870 if (is_compound_entity(ent)) {
1871 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1872 value = get_compound_ent_value(ent, i);
1874 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1875 dump_const_expression(F, value);
1876 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1878 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1879 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1880 get_compound_ent_value_member(ent, i), i);
1889 ir_type *tp = (ir_type *)tore;
1890 dump_type_node(F, tp);
1891 /* and now the edges */
1892 switch (get_type_tpop_code(tp)) {
1895 for (i=0; i < get_class_n_supertypes(tp); i++)
1896 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1897 for (i=0; i < get_class_n_members(tp); i++)
1898 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1902 for (i=0; i < get_struct_n_members(tp); i++)
1903 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1907 for (i = 0; i < get_method_n_params(tp); i++)
1908 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1909 for (i = 0; i < get_method_n_ress(tp); i++)
1910 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1914 for (i = 0; i < get_union_n_members(tp); i++)
1915 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1919 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1920 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1921 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1922 ir_node *upper = get_array_upper_bound(tp, i);
1923 ir_node *lower = get_array_lower_bound(tp, i);
1924 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1925 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1926 dump_const_expression(F, upper);
1927 dump_const_expression(F, lower);
1931 case tpo_enumeration:
1933 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1934 dump_enum_item(F, tp, i);
1935 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1940 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1948 break; /* case k_type */
1951 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1953 } /* switch kind_or_entity */
1956 typedef struct _h_env {
1961 /** For dumping class hierarchies.
1962 * Dumps a class type node and a superclass edge.
1963 * If env->dump_ent dumps entities of classes and overwrites edges.
1966 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1969 int i = 0; /* to shutup gcc */
1971 /* dump this type or entity */
1972 switch (get_kind(tore)) {
1974 entity *ent = (entity *)tore;
1975 if (get_entity_owner(ent) == get_glob_type()) break;
1976 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1977 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1979 dump_entity_node(F, ent, 0);
1981 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1982 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1983 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1985 } break; /* case k_entity */
1988 ir_type *tp = (ir_type *)tore;
1989 if (tp == get_glob_type()) break;
1990 switch (get_type_tpop_code(tp)) {
1992 dump_type_node(F, tp);
1993 /* and now the edges */
1994 for (i=0; i < get_class_n_supertypes(tp); i++)
1996 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
2002 break; /* case k_type */
2005 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
2007 } /* switch kind_or_entity */
2010 /*******************************************************************/
2011 /* dump analysis information that is expressed in graph terms. */
2012 /*******************************************************************/
2014 /* dump out edges */
2016 dump_out_edge(ir_node *n, void *env) {
2019 for (i = 0; i < get_irn_n_outs(n); i++) {
2020 assert(get_irn_out(n, i));
2021 fprintf (F, "edge: {sourcename: \"");
2023 fprintf (F, "\" targetname: \"");
2024 PRINT_NODEID(get_irn_out(n, i));
2025 fprintf (F, "\" color: red linestyle: dashed");
2031 dump_loop_label(FILE *F, ir_loop *loop) {
2032 fprintf (F, "loop %d, %d sons, %d nodes",
2033 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
2036 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
2037 fprintf (F, " info1: \"");
2038 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
2039 #if DEBUG_libfirm /* GL @@@ debug analyses */
2040 fprintf (F, "\n The loop was analyzed %d times.", PTR_TO_INT(get_loop_link(loop)));
2046 dump_loop_node(FILE *F, ir_loop *loop) {
2047 fprintf (F, "node: {title: \"");
2049 fprintf (F, "\" label: \"");
2050 dump_loop_label(F, loop);
2052 dump_loop_info(F, loop);
2058 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
2060 fprintf (F, "edge: {sourcename: \"");
2062 fprintf (F, "\" targetname: \"");
2063 PRINT_NODEID(get_loop_node(loop, i));
2064 fprintf (F, "\" color: green");
2069 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
2071 fprintf (F, "edge: {sourcename: \"");
2073 fprintf (F, "\" targetname: \"");
2074 PRINT_LOOPID(get_loop_son(loop, i));
2075 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
2076 get_loop_element_pos(loop, get_loop_son(loop, i)));
2080 void dump_loops(FILE *F, ir_loop *loop) {
2082 /* dump this loop node */
2083 dump_loop_node(F, loop);
2085 /* dump edges to nodes in loop -- only if it is a real loop */
2086 if (get_loop_depth(loop) != 0) {
2087 for (i = 0; i < get_loop_n_nodes(loop); i++) {
2088 dump_loop_node_edge(F, loop, i);
2091 for (i = 0; i < get_loop_n_sons(loop); i++) {
2092 dump_loops(F, get_loop_son(loop, i));
2093 dump_loop_son_edge(F, loop, i);
2098 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
2099 ir_graph *rem = current_ir_graph;
2100 current_ir_graph = irg;
2102 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
2104 current_ir_graph = rem;
2109 * dumps the VCG header
2111 void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
2120 if (!orientation) orientation = "bottom_to_top";
2124 "graph: { title: \"ir graph of %s\"\n"
2125 "display_edge_labels: %s\n"
2126 "layoutalgorithm: mindepth\n"
2127 "manhattan_edges: yes\n"
2128 "port_sharing: no\n"
2130 "classname 1: \"intrablock Data\"\n"
2131 "classname 2: \"Block\"\n"
2132 "classname 3: \"Entity type\"\n"
2133 "classname 4: \"Entity owner\"\n"
2134 "classname 5: \"Method Param\"\n"
2135 "classname 6: \"Method Res\"\n"
2136 "classname 7: \"Super\"\n"
2137 "classname 8: \"Union\"\n"
2138 "classname 9: \"Points-to\"\n"
2139 "classname 10: \"Array Element Type\"\n"
2140 "classname 11: \"Overwrites\"\n"
2141 "classname 12: \"Member\"\n"
2142 "classname 13: \"Control Flow\"\n"
2143 "classname 14: \"intrablock Memory\"\n"
2144 "classname 15: \"Dominators\"\n"
2145 "classname 16: \"interblock Data\"\n"
2146 "classname 17: \"interblock Memory\"\n"
2147 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
2148 "classname 19: \"Postdominators\"\n"
2149 "infoname 1: \"Attribute\"\n"
2150 "infoname 2: \"Verification errors\"\n"
2151 "infoname 3: \"Debug info\"\n",
2152 name, label, orientation);
2154 /* don't use all, the range is too whith/black. */
2158 "colorentry 100: 0 0 0\n"
2159 "colorentry 101: 20 0 0\n"
2160 "colorentry 102: 40 0 0\n"
2161 "colorentry 103: 60 0 0\n"
2162 "colorentry 104: 80 0 0\n"
2163 "colorentry 105: 100 0 0\n"
2164 "colorentry 106: 120 0 0\n"
2165 "colorentry 107: 140 0 0\n"
2166 "colorentry 108: 150 0 0\n"
2167 "colorentry 109: 180 0 0\n"
2168 "colorentry 110: 200 0 0\n"
2169 "colorentry 111: 220 0 0\n"
2170 "colorentry 112: 240 0 0\n"
2171 "colorentry 113: 255 0 0\n"
2172 "colorentry 113: 255 20 20\n"
2173 "colorentry 114: 255 40 40\n"
2174 "colorentry 115: 255 60 60\n"
2175 "colorentry 116: 255 80 80\n"
2176 "colorentry 117: 255 100 100\n"
2177 "colorentry 118: 255 120 120\n"
2178 "colorentry 119: 255 140 140\n"
2179 "colorentry 120: 255 150 150\n"
2180 "colorentry 121: 255 180 180\n"
2181 "colorentry 122: 255 200 200\n"
2182 "colorentry 123: 255 220 220\n"
2183 "colorentry 124: 255 240 240\n"
2184 "colorentry 125: 255 250 250\n"
2187 fprintf (F, "\n"); /* a separator */
2193 * @param irg The graph to be dumped
2194 * @param suffix1 first filename suffix
2195 * @param suffix2 second filename suffix
2197 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2199 const char *nm = get_irg_dump_name(irg);
2200 int len = strlen(nm), i, j;
2201 char *fname; /* filename to put the vcg information in */
2203 if (!suffix1) suffix1 = "";
2204 if (!suffix2) suffix2 = "";
2206 /* open file for vcg graph */
2207 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2209 /* strncpy (fname, nm, len); */ /* copy the filename */
2211 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2213 fname[j] = '@'; j++; fname[j] = '1'; j++;
2214 } else if (nm[i] == '@') {
2215 fname[j] = '@'; j++; fname[j] = '2'; j++;
2217 fname[j] = nm[i]; j++;
2221 strcat (fname, suffix1); /* append file suffix */
2222 strcat (fname, suffix2); /* append file suffix */
2223 strcat (fname, ".vcg"); /* append the .vcg suffix */
2225 /* vcg really expect only a <CR> at end of line, so
2226 * the "b"inary mode is what you mean (and even needed for Win32)
2228 F = fopen (fname, "wb"); /* open file for writing */
2230 panic("cannot open %s for writing (%m)", fname); /* not reached */
2240 * @param name prefix file name
2241 * @param suffix filename suffix
2243 FILE *vcg_open_name (const char *name, const char *suffix) {
2245 char *fname; /* filename to put the vcg information in */
2246 int i, j, len = strlen(name);
2248 if (!suffix) suffix = "";
2250 /** open file for vcg graph */
2251 fname = xmalloc(len * 2 + 5 + strlen(suffix));
2252 /* strcpy (fname, name);*/ /* copy the filename */
2254 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2255 if (name[i] == '/') {
2256 fname[j] = '@'; j++; fname[j] = '1'; j++;
2257 } else if (name[i] == '@') {
2258 fname[j] = '@'; j++; fname[j] = '2'; j++;
2260 fname[j] = name[i]; j++;
2264 strcat (fname, suffix);
2265 strcat (fname, ".vcg"); /* append the .vcg suffix */
2267 /* vcg really expect only a <CR> at end of line, so
2268 * the "b"inary mode is what you mean (and even needed for Win32)
2270 F = fopen (fname, "wb"); /* open file for writing */
2272 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2280 * Dumps the vcg file footer
2282 static INLINE void dump_vcg_footer (FILE *F) {
2287 * close the vcg file
2289 void vcg_close (FILE *F) {
2290 dump_vcg_footer(F); /* print footer */
2291 fclose (F); /* close vcg file */
2294 /************************************************************************/
2295 /************************************************************************/
2296 /* Routines that dump all or parts of the firm representation to a file */
2297 /************************************************************************/
2298 /************************************************************************/
2300 /************************************************************************/
2301 /* Dump ir graphs, different formats and additional information. */
2302 /************************************************************************/
2304 /** Routine to dump a graph, blocks as conventional nodes. */
2306 dump_ir_graph (ir_graph *irg, const char *suffix )
2311 rem = current_ir_graph;
2313 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2315 current_ir_graph = irg;
2316 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2317 else suffix1 = "-pure";
2318 f = vcg_open(irg, suffix, suffix1);
2319 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2321 /* call the dump graph hook */
2322 if (dump_ir_graph_hook)
2323 if (dump_ir_graph_hook(f, irg))
2326 /* walk over the graph */
2327 /* dump_whole_node must be called in post visiting predecessors */
2328 ird_walk_graph(irg, NULL, dump_whole_node, f);
2330 /* dump the out edges in a separate walk */
2331 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2332 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2337 current_ir_graph = rem;
2340 /* Dump a firm graph without explicit block nodes. */
2341 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2347 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2350 if (get_interprocedural_view()) suffix1 = "-ip";
2352 f = vcg_open(irg, suffix, suffix1);
2353 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2355 construct_block_lists(irg);
2358 * If we are in the interprocedural view, we dump not
2359 * only the requested irg but also all irgs that can be reached
2362 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2363 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2365 dump_graph_from_list(f, get_irp_irg(i));
2373 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2374 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2381 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2384 if (get_irg_extblk_state(irg) != extblk_valid)
2387 if (get_interprocedural_view()) suffix1 = "-ip";
2390 ent = get_irg_entity(irg);
2392 F = vcg_open(irg, suffix, suffix1);
2393 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2395 construct_extblock_lists(irg);
2397 fprintf(F, "graph: { title: \"");
2399 fprintf(F, "\" label: \"%s\" status:clustered color: white \n",
2400 get_ent_dump_name(ent));
2402 dump_graph_info(F, irg);
2403 print_dbg_info(F, get_entity_dbg_info(ent));
2405 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2406 ir_graph *irg = get_irp_irg(i);
2407 list_tuple *lists = ird_get_irg_link(irg);
2410 /* dump the extended blocks first */
2411 if (ARR_LEN(lists->extbb_list)) {
2412 ird_set_irg_link(irg, lists->extbb_list);
2413 dump_extblock_graph(F, irg);
2416 /* we may have blocks without extended blocks, bad for instance */
2417 if (ARR_LEN(lists->blk_list)) {
2418 ird_set_irg_link(irg, lists->blk_list);
2419 dump_block_graph(F, irg);
2422 DEL_ARR_F(lists->extbb_list);
2423 DEL_ARR_F(lists->blk_list);
2428 /* Close the vcg information for the irg */
2429 fprintf(F, "}\n\n");
2435 /* dumps a graph with type information */
2437 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2440 ir_graph *rem = current_ir_graph;
2442 int rem_dump_const_local;
2444 /* if a filter is set, dump only the irg's that match the filter */
2445 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2448 current_ir_graph = irg;
2449 rem_dump_const_local = dump_const_local;
2450 /* dumping types does not work with local nodes */
2451 dump_const_local = 0;
2453 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2454 else suffix1 = "-pure-wtypes";
2455 f = vcg_open(irg,suffix, suffix1);
2456 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2458 /* dump common ir graph */
2459 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2460 /* dump type info */
2461 type_walk_irg(irg, dump_type_info, NULL, f);
2462 inc_irg_visited(get_const_code_irg());
2463 /* dump edges from graph to type info */
2464 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2467 dump_const_local = rem_dump_const_local;
2468 current_ir_graph = rem;
2472 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2477 ir_graph *rem = current_ir_graph;
2478 int rem_dump_const_local;
2480 /* if a filter is set, dump only the irg's that match the filter */
2481 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2484 rem_dump_const_local = dump_const_local;
2485 /* dumping types does not work with local nodes */
2486 dump_const_local = 0;
2488 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2489 else suffix1 = "-wtypes";
2490 f = vcg_open(irg, suffix, suffix1);
2491 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2493 /* dump common blocked ir graph */
2494 construct_block_lists(irg);
2496 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2497 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2499 dump_graph_from_list(f, get_irp_irg(i));
2504 /* dump type info */
2505 current_ir_graph = irg;
2506 type_walk_irg(irg, dump_type_info, NULL, f);
2507 inc_irg_visited(get_const_code_irg());
2509 /* dump edges from graph to type info */
2510 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2513 dump_const_local = rem_dump_const_local;
2514 current_ir_graph = rem;
2517 /*---------------------------------------------------------------------*/
2518 /* The following routines dump a control flow graph. */
2519 /*---------------------------------------------------------------------*/
2522 dump_block_to_cfg(ir_node *block, void *env) {
2527 if (is_Block(block)) {
2528 /* This is a block. Dump a node for the block. */
2529 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2530 fprintf (F, "\" label: \"");
2531 if (block == get_irg_start_block(get_irn_irg(block)))
2532 fprintf(F, "Start ");
2533 if (block == get_irg_end_block(get_irn_irg(block)))
2536 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2537 PRINT_NODEID(block);
2539 fprintf(F, "info1:\"");
2541 /* the generic version. */
2542 dump_irnode_to_file(F, block);
2544 /* Check whether we have bad predecessors to color the block. */
2545 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2546 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2549 fprintf (F, "\""); /* closing quote of info */
2551 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2552 (block == get_irg_end_block(get_irn_irg(block))) )
2553 fprintf(F, " color:blue ");
2555 fprintf(F, " color:yellow ");
2558 /* Dump the edges */
2559 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2560 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2561 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2562 fprintf (F, "edge: { sourcename: \"");
2563 PRINT_NODEID(block);
2564 fprintf (F, "\" targetname: \"");
2566 fprintf (F, "\"}\n");
2569 /* Dump dominator/postdominator edge */
2570 if (dump_dominator_information_flag) {
2571 if (get_irg_dom_state(current_ir_graph) == dom_consistent && get_Block_idom(block)) {
2572 pred = get_Block_idom(block);
2573 fprintf (F, "edge: { sourcename: \"");
2574 PRINT_NODEID(block);
2575 fprintf (F, "\" targetname: \"");
2577 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2579 if (get_irg_postdom_state(current_ir_graph) == dom_consistent && get_Block_ipostdom(block)) {
2580 pred = get_Block_ipostdom(block);
2581 fprintf (F, "edge: { sourcename: \"");
2582 PRINT_NODEID(block);
2583 fprintf (F, "\" targetname: \"");
2585 fprintf (F, "\" " POSTDOMINATOR_EDGE_ATTR "}\n");
2592 dump_cfg (ir_graph *irg, const char *suffix)
2595 ir_graph *rem = current_ir_graph;
2596 int ipv = get_interprocedural_view();
2598 /* if a filter is set, dump only the irg's that match the filter */
2599 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2602 current_ir_graph = irg;
2604 f = vcg_open(irg, suffix, "-cfg");
2605 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2608 printf("Warning: dumping cfg not in interprocedural view!\n");
2609 set_interprocedural_view(0);
2612 /* walk over the blocks in the graph */
2613 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2614 dump_node(f, get_irg_bad(irg));
2616 set_interprocedural_view(ipv);
2618 current_ir_graph = rem;
2622 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2623 if (pset_find_ptr(mark_set, n)) return;
2625 pset_insert_ptr(mark_set, n);
2628 int i, start = is_Block(n) ? 0 : -1;
2629 dump_whole_node(n, F);
2630 for (i = start; i < get_irn_arity(n); ++i)
2631 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2634 /* Don't dump edges to nodes further out. These might be edges to
2635 nodes we already dumped, if there is a shorter path to these. */
2639 static int subgraph_counter = 0;
2640 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2643 pset *mark_set = pset_new_ptr(1);
2644 sprintf(buf, "-subg_%03d", subgraph_counter++);
2645 F = vcg_open(get_irn_irg(root), suffix, buf);
2646 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2647 descend_and_dump(F, root, depth, mark_set);
2653 static int weight_overall(int rec, int loop) {
2654 return 2*rec + loop;
2657 static int compute_color (int my, int max) {
2664 /* if small, scale to the full color range. */
2666 my = my * (n_colors/max);
2668 step = 1 + (max / n_colors);
2672 return base_color + n_colors - color;
2675 static int get_entity_color(entity *ent) {
2676 ir_graph *irg = get_entity_irg(ent);
2680 int rec_depth = get_irg_recursion_depth(irg);
2681 int loop_depth = get_irg_loop_depth(irg);
2682 int overall_depth = weight_overall(rec_depth, loop_depth);
2684 int max_rec_depth = irp->max_callgraph_recursion_depth;
2685 int max_loop_depth = irp->max_callgraph_loop_depth;
2686 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2688 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2689 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2690 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2692 return my_overall_color;
2696 void dump_callgraph(const char *suffix) {
2699 int rem = edge_label;
2701 //ident *prefix = new_id_from_str("java/");
2703 F = vcg_open_name("Callgraph", suffix);
2704 dump_vcg_header(F, "Callgraph", NULL);
2706 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2707 ir_graph *irg = get_irp_irg(i);
2708 entity *ent = get_irg_entity(irg);
2709 int j, n_callees = get_irg_n_callees(irg);
2711 /* Do not dump runtime system. */
2712 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2714 dump_entity_node(F, ent, get_entity_color(ent));
2715 for (j = 0; j < n_callees; ++j) {
2716 entity *c = get_irg_entity(get_irg_callee(irg, j));
2717 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2718 int be = is_irg_callee_backedge(irg, j);
2721 "label:\"recursion %d\" color:%d" :
2722 "label:\"calls %d\" color:%d";
2723 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2731 /* Dump all irgs in interprocedural view to a single file. */
2732 void dump_all_cg_block_graph(const char *suffix) {
2735 int rem_view = get_interprocedural_view();
2736 set_interprocedural_view(1);
2738 f = vcg_open_name("All_graphs", suffix);
2739 dump_vcg_header(f, "All_graphs", NULL);
2741 /* collect nodes in all irgs reachable in call graph*/
2742 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2743 ird_set_irg_link(get_irp_irg(i), NULL);
2745 cg_walk(clear_link, collect_node, NULL);
2747 /* dump all graphs */
2748 for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
2749 current_ir_graph = get_irp_irg(i);
2750 assert(ird_get_irg_link(current_ir_graph));
2751 dump_graph_from_list(f, current_ir_graph);
2752 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2756 set_interprocedural_view(rem_view);
2759 /*---------------------------------------------------------------------*/
2760 /* the following routines dumps type information without any ir nodes. */
2761 /*---------------------------------------------------------------------*/
2764 dump_type_graph (ir_graph *irg, const char *suffix)
2768 rem = current_ir_graph;
2770 /* if a filter is set, dump only the irg's that match the filter */
2771 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2773 current_ir_graph = irg;
2775 f = vcg_open(irg, suffix, "-type");
2776 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2778 /* walk over the blocks in the graph */
2779 type_walk_irg(irg, dump_type_info, NULL, f);
2780 /* The walker for the const code can be called several times for the
2781 same (sub) expression. So that no nodes are dumped several times
2782 we decrease the visited flag of the corresponding graph after each
2783 walk. So now increase it finally. */
2784 inc_irg_visited(get_const_code_irg());
2787 current_ir_graph = rem;
2791 dump_all_types (const char *suffix)
2793 FILE *f = vcg_open_name("All_types", suffix);
2794 dump_vcg_header(f, "All_types", NULL);
2795 type_walk(dump_type_info, NULL, f);
2796 inc_irg_visited(get_const_code_irg());
2801 dump_class_hierarchy (int entities, const char *suffix)
2803 FILE *f = vcg_open_name("class_hierarchy", suffix);
2807 env.dump_ent = entities;
2808 dump_vcg_header(f, "class_hierarchy", NULL);
2809 type_walk(dump_class_hierarchy_node, NULL, &env);
2813 /*---------------------------------------------------------------------*/
2814 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2816 /* dump_ir_block_graph */
2818 /* dump_type_graph */
2819 /* dump_ir_graph_w_types */
2820 /*---------------------------------------------------------------------*/
2822 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2824 for (i = get_irp_n_irgs() - 1; i >= 0; --i)
2825 dmp_grph(get_irp_irg(i), suffix);
2829 /*--------------------------------------------------------------------------------*
2830 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2831 * packed together in one subgraph/box *
2832 *--------------------------------------------------------------------------------*/
2834 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2835 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2837 ir_loop *son = NULL;
2839 /* Dump a new loop node. */
2840 dump_loop_node(F, loop);
2842 /* Dump the loop elements. */
2844 for(i = 0; i < get_loop_n_elements(loop); i++) {
2845 le = get_loop_element(loop, i);
2847 if (get_kind(son) == k_ir_loop) {
2849 /* We are a loop son -> Recurse */
2851 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2852 fprintf(F, "\" }\n");
2853 fprintf (F, "edge: {sourcename: \"");
2855 fprintf (F, "\" targetname: \"");
2857 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2858 loop_node_started = 0;
2860 dump_loop_son_edge(F, loop, son_number++);
2861 dump_loops_standalone(F, son);
2862 } else if (get_kind(son) == k_ir_node) {
2863 /* We are a loop node -> Collect firm nodes */
2865 ir_node *n = le.node;
2868 if (!loop_node_started) {
2869 /* Start a new node which contains all firm nodes of the current loop */
2870 fprintf (F, "node: { title: \"");
2872 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2873 loop_node_started = 1;
2879 bad |= dump_node_label(F, n);
2880 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2881 if (has_backedges(n)) fprintf(F, "\t loop head!");
2882 } else { /* for callgraph loop tree */
2884 assert(get_kind(son) == k_ir_graph);
2886 /* We are a loop node -> Collect firm graphs */
2887 n = (ir_graph *)le.node;
2888 if (!loop_node_started) {
2889 /* Start a new node which contains all firm nodes of the current loop */
2890 fprintf (F, "node: { title: \"");
2892 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2893 loop_node_started = 1;
2898 fprintf (F, " %s", get_irg_dump_name(n));
2899 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2903 if (loop_node_started) {
2904 fprintf(F, "\" }\n");
2905 fprintf (F, "edge: {sourcename: \"");
2907 fprintf (F, "\" targetname: \"");
2909 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2910 loop_node_started = 0;
2914 void dump_loop_tree(ir_graph *irg, const char *suffix)
2917 ir_graph *rem = current_ir_graph;
2918 int el_rem = edge_label;
2921 /* if a filter is set, dump only the irg's that match the filter */
2922 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2924 current_ir_graph = irg;
2926 f = vcg_open(irg, suffix, "-looptree");
2927 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2929 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2933 edge_label = el_rem;
2934 current_ir_graph = rem;
2937 void dump_callgraph_loop_tree(const char *suffix) {
2939 F = vcg_open_name("Callgraph_looptree", suffix);
2940 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2941 dump_loops_standalone(F, irp->outermost_cg_loop);
2946 /*-----------------------------------------------------------------------------*/
2947 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2948 /*-----------------------------------------------------------------------------*/
2950 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2951 int i, son_number = 0, node_number = 0;
2953 if (dump_loop_information_flag) dump_loop_node(F, loop);
2955 for (i = 0; i < get_loop_n_elements(loop); i++) {
2956 loop_element le = get_loop_element(loop, i);
2957 if (*(le.kind) == k_ir_loop) {
2958 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2960 collect_nodeloop(F, le.son, loopnodes);
2962 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2963 eset_insert(loopnodes, le.node);
2968 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2971 for(i = 0; i < get_loop_n_elements(loop); i++) {
2972 loop_element le = get_loop_element(loop, i);
2973 if (*(le.kind) == k_ir_loop) {
2975 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2977 if (is_Block(le.node)) start = 0; else start = -1;
2978 for (j = start; j < get_irn_arity(le.node); j++) {
2979 ir_node *pred = get_irn_n(le.node, j);
2980 if (!eset_contains(loopnodes, pred)) {
2981 eset_insert(extnodes, pred);
2982 if (!is_Block(pred)) {
2983 pred = get_nodes_block(pred);
2984 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2992 void dump_loop(ir_loop *l, const char *suffix) {
2995 eset *loopnodes = eset_create();
2996 eset *extnodes = eset_create();
2999 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
3000 F = vcg_open_name (name, suffix);
3001 dump_vcg_header(F, name, NULL);
3003 /* collect all nodes to dump */
3004 collect_nodeloop(F, l, loopnodes);
3005 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
3007 /* build block lists */
3008 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3009 set_irn_link(n, NULL);
3010 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3011 set_irn_link(n, NULL);
3012 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
3014 b = get_nodes_block(n);
3015 set_irn_link(n, get_irn_link(b));
3018 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
3020 b = get_nodes_block(n);
3021 set_irn_link(n, get_irn_link(b));
3025 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
3027 fprintf(F, "graph: { title: \"");
3029 fprintf(F, "\" label: \"");
3030 dump_node_opcode(F, b);
3031 fprintf (F, " %ld", get_irn_node_nr(b));
3032 fprintf(F, "\" status:clustered color:yellow\n");
3034 /* dump the blocks edges */
3035 dump_ir_data_edges(F, b);
3037 /* dump the nodes that go into the block */
3038 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3039 if (eset_contains(extnodes, n))
3040 overrule_nodecolor = ird_color_lightblue;
3042 overrule_nodecolor = ird_color_default;
3043 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
3046 /* Close the vcg information for the block */
3048 dump_const_node_local(F, b);
3051 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
3053 fprintf(F, "graph: { title: \"");
3055 fprintf(F, "\" label: \"");
3056 dump_node_opcode(F, b);
3057 fprintf (F, " %ld", get_irn_node_nr(b));
3058 fprintf(F, "\" status:clustered color:lightblue\n");
3060 /* dump the nodes that go into the block */
3061 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
3062 if (!eset_contains(loopnodes, n))
3063 overrule_nodecolor = ird_color_lightblue;
3065 overrule_nodecolor = ird_color_default;
3066 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
3069 /* Close the vcg information for the block */
3071 dump_const_node_local(F, b);
3075 eset_destroy(loopnodes);
3076 eset_destroy(extnodes);