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"
27 #include "irgraph_t.h"
37 #include "type_or_entity.h"
41 #include "callgraph.h"
42 #include "irextbb_t.h"
43 #include "dbginfo_t.h"
54 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
55 extern void dump_irn_state(FILE *FL, ir_node *n);
56 extern int get_opt_dump_abstvals(void);
57 typedef unsigned long SeqNo;
58 extern SeqNo get_Block_seqno(ir_node *n);
61 /* basis for a color range for vcg */
62 static int n_colors = 0;
63 static int base_color = 0;
65 /** Dump only irgs with names that start with this string */
66 static ident *dump_file_filter_id = NULL;
68 #define ERROR_TXT "<ERROR>"
71 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
72 * in the later case, sets bad
74 const char *get_mode_name_ex(ir_mode *mode, int *bad)
77 return get_mode_name(mode);
83 * returns the name of a type or <ERROR> if mode is NOT a mode object.
84 * in the later case, sets bad
86 const char *get_type_name_ex(type *tp, int *bad)
89 return get_type_name(tp);
95 * prints the edge from a type S to a type T with additional info fmt, ...
98 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
103 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
104 fprintf(F, " targetname: "); PRINT_TYPEID(T);
105 vfprintf(F, fmt, ap);
111 * prints the edge from a type T to an entity E with additional info fmt, ...
114 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
119 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
120 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
121 vfprintf(F, fmt, ap);
127 * prints the edge from an entity E to an entity T with additional info fmt, ...
130 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
136 fprintf(F, "backedge: { sourcename: \"");
138 fprintf(F, "edge: { sourcename: \"");
140 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
141 vfprintf(F, fmt, ap);
147 * prints the edge from an entity E to a type T with additional info fmt, ...
150 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
155 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
156 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
157 vfprintf(F, fmt, ap);
163 * prints the edge from a node N to a type T with additional info fmt, ...
166 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
171 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
172 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
173 vfprintf(F, fmt, ap);
179 * prints the edge from a node N to an entity E with additional info fmt, ...
182 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
187 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
188 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
190 vfprintf(F, fmt, ap);
196 * prints the edge from an entity E to a node N with additional info fmt, ...
199 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
204 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
205 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
206 vfprintf(F, fmt, ap);
212 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
215 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
220 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
221 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
222 vfprintf(F, fmt, ap);
227 /*-----------------------------------------------------------------*/
228 /* global and ahead declarations */
229 /*-----------------------------------------------------------------*/
231 static void dump_whole_node(ir_node *n, void *env);
232 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
234 /*-----------------------------------------------------------------*/
235 /* Helper functions. */
236 /*-----------------------------------------------------------------*/
239 * This map is used as a private link attr to be able to call dumper
240 * anywhere without destroying link fields.
242 static pmap *irdump_link_map = NULL;
244 /** NOT A STANDARD LIBFIRM INIT METHOD
246 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
247 * are off, we want to have as few interferences as possible. Therefore the
248 * initialization is performed lazily and not called from within init_firm.
250 * Creates the link attribute map. */
251 static void init_irdump(void) {
252 /* We need a new, empty map. */
253 if (irdump_link_map) pmap_destroy(irdump_link_map);
254 irdump_link_map = pmap_create();
255 if (!dump_file_filter_id)
256 dump_file_filter_id = new_id_from_str("");
259 * Returns the private link field.
261 static void *ird_get_irn_link(ir_node *n) {
263 if (!irdump_link_map) return NULL;
265 if (pmap_contains(irdump_link_map, (void *)n))
266 res = pmap_get(irdump_link_map, (void *)n);
271 * Sets the private link field.
273 static void ird_set_irn_link(ir_node *n, void *x) {
274 if (!irdump_link_map) init_irdump();
275 pmap_insert(irdump_link_map, (void *)n, x);
279 * Gets the private link field of an irg.
281 static void *ird_get_irg_link(ir_graph *irg) {
283 if (!irdump_link_map) return NULL;
285 if (pmap_contains(irdump_link_map, (void *)irg))
286 res = pmap_get(irdump_link_map, (void *)irg);
291 * Sets the private link field of an irg.
293 static void ird_set_irg_link(ir_graph *irg, void *x) {
294 if (!irdump_link_map) init_irdump();
295 pmap_insert(irdump_link_map, (void *)irg, x);
299 * Walker, clears the private link field.
301 static void clear_link(ir_node * node, void * env) {
302 ird_set_irn_link(node, NULL);
306 * If the entity has a ld_name, returns it, else returns the name of the entity.
308 const char *get_ent_dump_name(entity *ent) {
310 return "<NULL entity>";
311 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
312 if (ent->ld_name) return get_id_str(ent->ld_name);
313 return get_id_str(ent->name);
316 /* Returns the name of an IRG. */
317 const char *get_irg_dump_name(ir_graph *irg) {
318 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
319 entity *ent = get_irg_entity(irg);
320 return get_ent_dump_name(ent);
324 * Returns non-zero if a node is in floating state.
326 static int node_floats(ir_node *n) {
327 return ((get_irn_pinned(n) == op_pin_state_floats) &&
328 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
332 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
334 static void collect_node(ir_node * node, void *env) {
337 || get_irn_op(node) == op_Bad
338 || get_irn_op(node) == op_Unknown
339 || get_irn_op(node) == op_NoMem) {
340 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
341 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
342 ARR_APP1(ir_node *, arr, node);
343 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
345 ir_node * block = get_nodes_block(node);
348 /* this node is in a Bad block, so we must place it into the graph's list */
349 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
350 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
351 ARR_APP1(ir_node *, arr, node);
352 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
355 ird_set_irn_link(node, ird_get_irn_link(block));
356 ird_set_irn_link(block, node);
361 /** Construct lists to walk ir block-wise.
363 * Collects all blocks, nodes not op_pin_state_pinned,
364 * Bad, NoMem and Unknown into a flexible array in link field of
365 * irg they belong to. Sets the irg link field to NULL in all
366 * graphs not visited.
367 * Free the list with DEL_ARR_F().
369 static ir_node **construct_block_lists(ir_graph *irg) {
370 int i, rem_view = get_interprocedural_view();
371 ir_graph *rem = current_ir_graph;
372 current_ir_graph = irg;
374 for (i = 0; i < get_irp_n_irgs(); i++)
375 ird_set_irg_link(get_irp_irg(i), NULL);
377 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
379 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
380 set_interprocedural_view(false);
382 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
383 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
384 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
385 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
387 set_interprocedural_view(rem_view);
389 current_ir_graph = rem;
390 return ird_get_irg_link(irg);
393 typedef struct _list_tuple {
395 ir_extblk **extbb_list;
398 /** Construct lists to walk ir extended block-wise.
399 * Free the lists in the tuple with DEL_ARR_F().
401 static list_tuple *construct_extblock_lists(ir_graph *irg) {
402 ir_node **blk_list = construct_block_lists(irg);
404 ir_graph *rem = current_ir_graph;
405 list_tuple *lists = xmalloc(sizeof(*lists));
407 current_ir_graph = irg;
409 lists->blk_list = NEW_ARR_F(ir_node *, 0);
410 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
412 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
415 if (is_Block(blk_list[i])) {
416 ext = get_Block_extbb(blk_list[i]);
418 if (extbb_not_visited(ext)) {
419 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
420 mark_extbb_visited(ext);
424 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
427 current_ir_graph = rem;
429 ird_set_irg_link(irg, lists);
433 /*******************************************************************/
434 /* flags to steer output */
435 /*******************************************************************/
437 /** A compiler option to turn off edge labels */
438 static int edge_label = 1;
439 /** A compiler option to turn off dumping values of constant entities */
440 static int const_entities = 1;
441 /** A compiler option to dump the keep alive edges */
442 static int dump_keepalive = 0;
443 /** Compiler options to dump analysis information in dump_ir_graph */
444 int dump_out_edge_flag = 0;
445 int dump_dominator_information_flag = 0;
446 int dump_loop_information_flag = 0;
447 int dump_backedge_information_flag = 1;
448 int dump_const_local = 0;
449 bool opt_dump_analysed_type_info = 1;
450 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
452 static const char *overrule_nodecolor = NULL;
454 /** An additional edge hook. */
455 static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;
457 void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func)
459 dump_node_edge_hook = func;
462 DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void)
464 return dump_node_edge_hook;
468 /** The vcg attribute hook. */
469 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
472 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
473 dump_node_vcgattr_hook = hook;
476 INLINE bool get_opt_dump_const_local(void) {
477 if (!dump_out_edge_flag && !dump_loop_information_flag)
478 return dump_const_local;
483 void only_dump_method_with_name(ident *name) {
484 dump_file_filter_id = name;
487 ident *get_dump_file_filter_ident(void) {
488 return dump_file_filter_id;
491 /** Returns true if dump file filter is not set, or if it is a
493 int is_filtered_dump_name(ident *name) {
494 if (!dump_file_filter_id) return 1;
495 return id_is_prefix(dump_file_filter_id, name);
498 /* To turn off display of edge labels. Edge labels offen cause xvcg to
499 abort with a segmentation fault. */
500 void turn_off_edge_labels(void) {
504 void dump_consts_local(bool b) {
505 dump_const_local = b;
508 void dump_constant_entity_values(bool b) {
512 void dump_keepalive_edges(bool b) {
516 bool get_opt_dump_keepalive_edges(void) {
517 return dump_keepalive;
520 void dump_out_edges(bool b) {
521 dump_out_edge_flag = b;
524 void dump_dominator_information(bool b) {
525 dump_dominator_information_flag = b;
528 void dump_loop_information(bool b) {
529 dump_loop_information_flag = b;
532 void dump_backedge_information(bool b) {
533 dump_backedge_information_flag = b;
536 /* Dump the information of type field specified in ana/irtypeinfo.h.
537 * If the flag is set, the type name is output in [] in the node label,
538 * else it is output as info.
540 void set_opt_dump_analysed_type_info(bool b) {
541 opt_dump_analysed_type_info = b;
544 void dump_pointer_values_to_info(bool b) {
545 opt_dump_pointer_values_to_info = b;
548 /*-----------------------------------------------------------------*/
549 /* Routines to dump information about a single ir node. */
550 /*-----------------------------------------------------------------*/
553 * dump the name of a node n to the File F.
556 dump_node_opcode(FILE *F, ir_node *n)
560 switch(get_irn_opcode(n)) {
565 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
566 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
571 if (get_SymConst_kind(n) == symconst_addr_name) {
572 /* don't use get_SymConst_ptr_info as it mangles the name. */
573 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
574 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
575 assert(get_SymConst_entity(n));
576 assert(is_entity(get_SymConst_entity(n)));
577 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
579 assert(get_kind(get_SymConst_type(n)) == k_type);
580 assert(get_type_ident(get_SymConst_type(n)));
581 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
582 if (get_SymConst_kind(n) == symconst_type_tag)
590 if (!get_interprocedural_view())
597 ir_node *pred = get_Proj_pred(n);
599 if (get_irn_opcode(pred) == iro_Cond
600 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
601 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
602 fprintf (F, "defProj");
610 if (get_interprocedural_view()) {
611 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
616 case iro_CallBegin: {
617 ir_node *addr = get_CallBegin_ptr(n);
619 if (get_irn_op(addr) == op_Sel)
620 ent = get_Sel_entity(addr);
621 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
622 ent = get_SymConst_entity(addr);
623 fprintf (F, "%s", get_irn_opname(n));
624 if (ent) fprintf (F, " %s", get_entity_name(ent));
628 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
633 fprintf (F, "%s", get_irn_opname(n));
641 * Dump the mode of a node n to a file F.
642 * Ignore modes that are "always known".
645 dump_node_mode(FILE *F, ir_node *n)
648 opcode iro = get_irn_opcode(n);
661 ir_mode *mode = get_irn_mode(n);
663 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
664 (mode != mode_T || iro == iro_Proj))
665 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
673 * Dump the type of a node n to a file F if it's known.
675 static int dump_node_typeinfo(FILE *F, ir_node *n) {
678 if (opt_dump_analysed_type_info) {
679 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
680 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
681 type *tp = get_irn_typeinfo_type(n);
682 if (tp != firm_none_type)
683 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
691 typedef struct _pns_lookup {
692 long nr; /**< the proj number */
693 const char *name; /**< the name of the Proj */
696 typedef struct _proj_lookup {
697 opcode code; /**< the opcode of the Proj predecessor */
698 unsigned num_data; /**< number of data entries */
699 const pns_lookup_t *data; /**< the data */
702 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
704 /** the lookup table for Proj(Start) names */
705 static const pns_lookup_t start_lut[] = {
706 #define X(a) { pn_Start_##a, #a }
715 /** the lookup table for Proj(Cond) names */
716 static const pns_lookup_t cond_lut[] = {
717 #define X(a) { pn_Cond_##a, #a }
723 /** the lookup table for Proj(Call) names */
724 static const pns_lookup_t call_lut[] = {
725 #define X(a) { pn_Call_##a, #a }
734 /** the lookup table for Proj(Quot) names */
735 static const pns_lookup_t quot_lut[] = {
736 #define X(a) { pn_Quot_##a, #a }
743 /** the lookup table for Proj(DivMod) names */
744 static const pns_lookup_t divmod_lut[] = {
745 #define X(a) { pn_DivMod_##a, #a }
753 /** the lookup table for Proj(Div) names */
754 static const pns_lookup_t div_lut[] = {
755 #define X(a) { pn_Div_##a, #a }
762 /** the lookup table for Proj(Mod) names */
763 static const pns_lookup_t mod_lut[] = {
764 #define X(a) { pn_Mod_##a, #a }
771 /** the lookup table for Proj(Load) names */
772 static const pns_lookup_t load_lut[] = {
773 #define X(a) { pn_Load_##a, #a }
780 /** the lookup table for Proj(Store) names */
781 static const pns_lookup_t store_lut[] = {
782 #define X(a) { pn_Store_##a, #a }
788 /** the lookup table for Proj(Alloc) names */
789 static const pns_lookup_t alloc_lut[] = {
790 #define X(a) { pn_Alloc_##a, #a }
798 /** the Proj lookup table */
799 static const proj_lookup_t proj_lut[] = {
800 #define E(a) ARR_SIZE(a), a
801 { iro_Start, E(start_lut) },
802 { iro_Cond, E(cond_lut) },
803 { iro_Call, E(call_lut) },
804 { iro_Quot, E(quot_lut) },
805 { iro_DivMod, E(divmod_lut) },
806 { iro_Div, E(div_lut) },
807 { iro_Mod, E(mod_lut) },
808 { iro_Load, E(load_lut) },
809 { iro_Store, E(store_lut) },
810 { iro_Alloc, E(alloc_lut) }
815 * Dump additional node attributes of some nodes to a file F.
818 dump_node_nodeattr(FILE *F, ir_node *n)
825 switch (get_irn_opcode(n)) {
827 if (false && get_interprocedural_view()) {
828 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
833 pred = get_Proj_pred(n);
834 proj_nr = get_Proj_proj(n);
836 code = get_irn_opcode(pred);
839 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
840 else if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
841 fprintf (F, "Arg %ld ", proj_nr);
843 unsigned i, j, f = 0;
845 for (i = 0; i < ARR_SIZE(proj_lut); ++i) {
846 if (code == proj_lut[i].code) {
847 for (j = 0; j < proj_lut[i].num_data; ++j) {
848 if (proj_nr == proj_lut[i].data[j].nr) {
849 fprintf (F, "%s ", proj_lut[i].data[j].name);
858 fprintf (F, "%ld ", proj_nr);
862 proj_nr = get_Filter_proj(n);
863 if (! get_interprocedural_view()) {
865 pred = get_Filter_pred(n);
869 fprintf (F, "%ld ", proj_nr);
872 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
875 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
878 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
889 #include "execution_frequency.h"
890 #include "callgraph.h"
892 void dump_node_ana_vals(FILE *F, ir_node *n) {
894 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
895 get_irn_exec_freq(n),
896 get_irg_method_execution_frequency(get_irn_irg(n)),
897 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
898 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
903 /* Dumps a node label without the enclosing ". */
904 int dump_node_label(FILE *F, ir_node *n) {
907 bad |= dump_node_opcode(F, n);
908 bad |= dump_node_mode(F, n);
910 bad |= dump_node_typeinfo(F, n);
911 bad |= dump_node_nodeattr(F, n);
912 fprintf(F, "%ld", get_irn_node_nr(n));
919 * Dumps the attributes of a node n into the file F.
920 * Currently this is only the color of a node.
922 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
927 fprintf(F, "color: red");
931 if (dump_node_vcgattr_hook)
932 if (dump_node_vcgattr_hook(F, node, local))
935 n = local ? local : node;
937 switch (get_irn_opcode(n)) {
944 fprintf (F, "color: blue");
947 if (is_Block_dead(n))
948 fprintf (F, "color: lightred");
950 fprintf (F, "color: lightyellow");
953 fprintf (F, "color: green");
959 fprintf (F, "color: yellow");
962 PRINT_DEFAULT_NODE_ATTR;
965 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
970 * Dump the node information of a node n to a file F.
972 static INLINE int dump_node_info(FILE *F, ir_node *n)
974 fprintf (F, " info1: \"");
975 bad = dump_irnode_to_file(F, n);
981 * checks whether a node is "constant-like" ie can be treated "block-less"
984 bool is_constlike_node(ir_node *n) {
985 ir_op *op = get_irn_op(n);
986 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
990 /** outputs the predecessors of n, that are constants, local. I.e.,
991 generates a copy of the constant predecessors for each node called with. */
992 static void dump_const_node_local(FILE *F, ir_node *n) {
994 if (!get_opt_dump_const_local()) return;
996 /* Use visited flag to avoid outputting nodes twice.
997 initialize it first. */
998 for (i = 0; i < get_irn_arity(n); i++) {
999 ir_node *con = get_irn_n(n, i);
1000 if (is_constlike_node(con)) {
1001 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
1005 for (i = 0; i < get_irn_arity(n); i++) {
1006 ir_node *con = get_irn_n(n, i);
1007 if (is_constlike_node(con) && irn_not_visited(con)) {
1010 mark_irn_visited(con);
1011 /* Generate a new name for the node by appending the names of
1013 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
1014 fprintf(F, " label: \"");
1015 bad |= dump_node_label(F, con);
1017 bad |= dump_node_info(F, con);
1018 dump_node_vcgattr(F, n, con, bad);
1024 /** If the block of an edge is a const_like node, dump it local with an edge */
1025 static void dump_const_block_local(FILE *F, ir_node *n) {
1028 if (!get_opt_dump_const_local()) return;
1030 blk = get_nodes_block(n);
1031 if (is_constlike_node(blk)) {
1034 /* Generate a new name for the node by appending the names of
1036 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
1037 fprintf(F, "\" label: \"");
1038 bad |= dump_node_label(F, blk);
1040 bad |= dump_node_info(F, blk);
1041 dump_node_vcgattr(F, n, blk, bad);
1044 fprintf (F, "edge: { sourcename: \"");
1046 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
1047 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
1052 * prints the error message of a node to a file F as info2.
1054 static void INLINE print_node_error(FILE *F, const char *err_msg)
1059 fprintf (F, " info2: \"%s\"", err_msg);
1063 * prints debug messages of a node to file F as info3.
1065 static void print_node_dbg_info(FILE *F, dbg_info *dbg)
1069 if (__dbg_info_snprint) {
1071 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
1072 fprintf (F, " info3: \"%s\"", buf);
1079 static void dump_node(FILE *F, ir_node *n)
1084 if (get_opt_dump_const_local() && is_constlike_node(n))
1087 /* dump this node */
1088 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
1090 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
1091 bad |= dump_node_label(F, n);
1092 dump_node_ana_vals(F, n);
1093 //dump_node_ana_info(F, n);
1095 bad |= dump_node_info(F, n);
1096 print_node_error(F, p);
1097 print_node_dbg_info(F, get_irn_dbg_info(n));
1098 dump_node_vcgattr(F, n, NULL, bad);
1100 dump_const_node_local(F, n);
1102 if(dump_node_edge_hook)
1103 dump_node_edge_hook(F, n);
1105 dump_irn_chi_term(F, n);
1106 dump_irn_state(F, n);
1110 /** dump the edge to the block this node belongs to */
1112 dump_ir_block_edge(FILE *F, ir_node *n) {
1113 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
1114 if (is_no_Block(n)) {
1115 ir_node *block = get_nodes_block(n);
1117 if (get_opt_dump_const_local() && is_constlike_node(block)) {
1118 dump_const_block_local(F, n);
1121 fprintf (F, "edge: { sourcename: \"");
1123 fprintf (F, "\" targetname: ");
1124 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
1125 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
1131 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
1133 * do not use get_nodes_block() here, will fail
1134 * if the irg is not pinned.
1136 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1137 fprintf (F, INTRA_DATA_EDGE_ATTR);
1139 fprintf (F, INTER_DATA_EDGE_ATTR);
1143 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1145 * do not use get_nodes_block() here, will fail
1146 * if the irg is not pinned.
1148 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1149 fprintf (F, INTRA_MEM_EDGE_ATTR);
1151 fprintf (F, INTER_MEM_EDGE_ATTR);
1155 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1158 if (dump_backedge_information_flag && is_backedge(from, to))
1159 fprintf (F, BACK_EDGE_ATTR);
1161 switch (get_irn_opcode(from)) {
1163 fprintf (F, CF_EDGE_ATTR);
1165 case iro_Start: break;
1168 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1169 fprintf (F, CF_EDGE_ATTR);
1170 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1171 fprintf (F, INTER_MEM_EDGE_ATTR);
1179 print_data_edge_vcgattr(F, from, to);
1184 print_mem_edge_vcgattr(F, from, to);
1186 print_data_edge_vcgattr(F, from, to);
1190 print_data_edge_vcgattr(F, from, to);
1195 print_mem_edge_vcgattr(F, from, to);
1197 print_data_edge_vcgattr(F, from, to);
1204 print_data_edge_vcgattr(F, from, to);
1211 print_mem_edge_vcgattr(F, from, to);
1213 print_data_edge_vcgattr(F, from, to);
1225 print_data_edge_vcgattr(F, from, to);
1228 if (get_irn_modecode(from) == irm_M)
1229 fprintf (F, INTER_MEM_EDGE_ATTR);
1231 print_data_edge_vcgattr(F, from, to);
1238 print_mem_edge_vcgattr(F, from, to);
1240 print_data_edge_vcgattr(F, from, to);
1243 print_mem_edge_vcgattr(F, from, to);
1245 case iro_Tuple: break;
1248 switch (get_irn_modecode(from)) {
1250 fprintf (F, CF_EDGE_ATTR);
1253 fprintf (F, INTER_MEM_EDGE_ATTR);
1256 print_data_edge_vcgattr(F, from, to);
1260 case iro_Bad: break;
1261 case iro_Unknown: break;
1263 switch (get_irn_modecode(from)) {
1265 fprintf (F, INTRA_MEM_EDGE_ATTR);
1268 fprintf (F, CF_EDGE_ATTR);
1271 print_data_edge_vcgattr(F, from, to);
1279 /* dump edges to our inputs */
1281 dump_ir_data_edges(FILE *F, ir_node *n) {
1283 unsigned long visited = get_irn_visited(n);
1285 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1288 for (i = 0; i < get_irn_arity(n); i++) {
1289 ir_node * pred = get_irn_n(n, i);
1292 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1293 continue; /* pred not dumped */
1295 if (dump_backedge_information_flag && is_backedge(n, i))
1296 fprintf (F, "backedge: {sourcename: \"");
1298 fprintf (F, "edge: {sourcename: \"");
1300 fprintf (F, "\" targetname: ");
1301 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1302 PRINT_CONSTID(n, pred);
1304 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1306 fprintf (F, " label: \"%d\" ", i);
1307 print_edge_vcgattr(F, n, i);
1312 /** Dumps a node and its edges but not the block edge
1315 dump_node_wo_blockedge (ir_node *n, void *env) {
1318 dump_ir_data_edges(F, n);
1321 /** Dumps a node and its edges.
1324 dump_whole_node (ir_node *n, void *env) {
1326 dump_node_wo_blockedge(n, env);
1327 if (!node_floats(n)) dump_ir_block_edge(F, n);
1331 dump_const_node(ir_node *n, void *env) {
1332 if (is_Block(n)) return;
1333 dump_node_wo_blockedge(n, env);
1336 /***********************************************************************/
1337 /* the following routines dump the nodes/irgs bracketed to graphs. */
1338 /***********************************************************************/
1340 /** Dumps a constant expression as entity initializer, array bound ...
1342 static void dump_const_expression(FILE *F, ir_node *value) {
1343 ir_graph *rem = current_ir_graph;
1344 int rem_dump_const_local = dump_const_local;
1345 dump_const_local = 0;
1346 current_ir_graph = get_const_code_irg();
1347 irg_walk(value, dump_const_node, NULL, F);
1348 /* Decrease visited flag so that we walk with the same flag for the next
1349 expression. This guarantees that we don't dump the same node twice,
1350 as for const expressions cse is performed to save memory. */
1351 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1352 current_ir_graph = rem;
1353 dump_const_local = rem_dump_const_local;
1356 /** Dump a block as graph containing its nodes.
1358 * Expects to find nodes belonging to the block as list in its
1360 * Dumps the edges of all nodes including itself. */
1362 dump_whole_block(FILE *F, ir_node *block) {
1364 assert(is_Block(block));
1366 fprintf(F, "graph: { title: \"");
1367 PRINT_NODEID(block);
1368 fprintf(F, "\" label: \"");
1369 dump_node_label(F, block);
1371 if (get_opt_dump_abstvals())
1372 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1374 fprintf(F, "\" status:clustered color:%s \n",
1375 get_Block_matured(block) ? "yellow" : "red");
1377 /* dump the blocks edges */
1378 dump_ir_data_edges(F, block);
1380 /* dump the nodes that go into the block */
1381 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1383 dump_ir_data_edges(F, node);
1386 /* Close the vcg information for the block */
1388 dump_const_node_local(F, block);
1390 dump_irn_chi_term(F, block);
1395 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1396 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1398 dump_block_graph(FILE *F, ir_graph *irg) {
1400 ir_graph *rem = current_ir_graph;
1401 ir_node **arr = ird_get_irg_link(irg);
1402 current_ir_graph = irg;
1404 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1405 ir_node * node = arr[i];
1406 if (is_Block(node)) {
1407 /* Dumps the block and all the nodes in the block, which are to
1408 be found in Block->link. */
1409 dump_whole_block(F, node);
1411 /* Nodes that are not in a Block. */
1413 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1414 dump_const_block_local(F, node);
1416 dump_ir_data_edges(F, node);
1420 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1421 dump_loop_nodes_into_graph(F, irg);
1423 current_ir_graph = rem;
1426 /** Dumps an irg as a graph clustered by block nodes.
1427 * If interprocedural view edges can point to nodes out of this graph.
1429 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1431 fprintf(F, "graph: { title: \"");
1433 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1434 get_ent_dump_name(get_irg_entity(irg)));
1436 dump_block_graph(F, irg);
1438 /* Close the vcg information for the irg */
1439 fprintf(F, "}\n\n");
1442 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1443 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1445 dump_extblock_graph(FILE *F, ir_graph *irg) {
1447 ir_graph *rem = current_ir_graph;
1448 ir_extblk **arr = ird_get_irg_link(irg);
1449 current_ir_graph = irg;
1452 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1453 ir_extblk *extbb = arr[i];
1454 ir_node *leader = extbb->blks[0];
1457 fprintf(F, "graph: { title: \"");
1458 PRINT_EXTBBID(leader);
1459 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1460 get_irn_node_nr(leader));
1462 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1463 ir_node * node = extbb->blks[j];
1464 if (is_Block(node)) {
1465 /* Dumps the block and all the nodes in the block, which are to
1466 be found in Block->link. */
1467 dump_whole_block(F, node);
1469 /* Nodes that are not in a Block. */
1471 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1472 dump_const_block_local(F, node);
1474 dump_ir_data_edges(F, node);
1480 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1481 dump_loop_nodes_into_graph(F, irg);
1483 current_ir_graph = rem;
1488 /*******************************************************************/
1489 /* Basic type and entity nodes and edges. */
1490 /*******************************************************************/
1492 /** dumps the edges between nodes and their type or entity attributes. */
1493 static void dump_node2type_edges(ir_node *n, void *env)
1498 switch (get_irn_opcode(n)) {
1500 /* @@@ some consts have an entity */
1503 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1504 || (get_SymConst_kind(n) ==symconst_size))
1506 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1510 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1513 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1516 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1519 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1522 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1530 static int print_type_info(FILE *F, type *tp) {
1533 if (get_type_state(tp) == layout_undefined) {
1534 fprintf(F, "state: layout_undefined\n");
1536 fprintf(F, "state: layout_fixed,\n");
1538 if (get_type_mode(tp))
1539 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1540 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1545 static void print_typespecific_info(FILE *F, type *tp) {
1546 switch (get_type_tpop_code(tp)) {
1549 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1556 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1557 fprintf(F, "params: %d\n", get_method_n_params(tp));
1558 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1566 case tpo_enumeration:
1580 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1581 switch (get_type_tpop_code(tp)) {
1584 if (peculiarity_existent == get_class_peculiarity(tp))
1585 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1587 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1591 fprintf (F, " " TYPE_METH_NODE_ATTR);
1602 case tpo_enumeration:
1616 /* Why not dump_type_node as the others? */
1617 static int print_type_node(FILE *F, type *tp)
1621 fprintf (F, "node: {title: ");
1623 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1624 fprintf (F, " info1: \"");
1626 bad |= print_type_info(F, tp);
1627 print_typespecific_info(F, tp);
1629 dump_type_to_file(F, tp, dump_verbosity_max);
1632 print_typespecific_vcgattr(F, tp);
1638 int dump_type_node(FILE *F, type *tp) {
1639 return print_type_node(F, tp);
1643 #define X(a) case a: fprintf(F, #a); break
1644 void dump_entity_node(FILE *F, entity *ent, int color)
1646 fprintf (F, "node: {title: \"");
1647 PRINT_ENTID(ent); fprintf(F, "\"");
1648 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1649 fprintf (F, "label: ");
1650 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1652 fprintf(F, "color: %d", color);
1654 fprintf (F, ENTITY_NODE_ATTR);
1655 fprintf (F, "\n info1: \"");
1657 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1659 fprintf(F, "\"\n}\n");
1663 static void dump_enum_item(FILE *F, type *tp, int pos)
1666 ident *id = get_enumeration_nameid(tp, pos);
1667 tarval *tv = get_enumeration_enum(tp, pos);
1669 tarval_snprintf(buf, sizeof(buf), tv);
1670 fprintf (F, "node: {title: \"");
1671 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1672 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1673 fprintf (F, "label: ");
1674 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1675 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1678 /* dumps a type or entity and it's edges. */
1680 dump_type_info(type_or_ent *tore, void *env) {
1682 int i = 0; /* to shutup gcc */
1684 /* dump this type or entity */
1686 switch (get_kind(tore)) {
1689 entity *ent = (entity *)tore;
1692 dump_entity_node(F, ent, 0);
1694 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1695 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1696 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1697 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1698 if (is_Class_type(get_entity_owner(ent))) {
1699 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1700 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1702 /* attached subgraphs */
1703 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1704 if (is_atomic_entity(ent)) {
1705 value = get_atomic_ent_value(ent);
1707 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1708 /* DDMN(value); $$$ */
1709 dump_const_expression(F, value);
1712 if (is_compound_entity(ent)) {
1713 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1714 value = get_compound_ent_value(ent, i);
1716 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1717 dump_const_expression(F, value);
1718 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1720 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1721 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1722 get_compound_ent_value_member(ent, i), i);
1731 type *tp = (type *)tore;
1732 print_type_node(F, tp);
1733 /* and now the edges */
1734 switch (get_type_tpop_code(tp)) {
1737 for (i=0; i < get_class_n_supertypes(tp); i++)
1738 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1739 for (i=0; i < get_class_n_members(tp); i++)
1740 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1744 for (i=0; i < get_struct_n_members(tp); i++)
1745 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1749 for (i = 0; i < get_method_n_params(tp); i++)
1750 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1751 for (i = 0; i < get_method_n_ress(tp); i++)
1752 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1756 for (i = 0; i < get_union_n_members(tp); i++)
1757 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1761 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1762 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1763 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1764 ir_node *upper = get_array_upper_bound(tp, i);
1765 ir_node *lower = get_array_lower_bound(tp, i);
1766 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1767 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1768 dump_const_expression(F, upper);
1769 dump_const_expression(F, lower);
1773 case tpo_enumeration:
1775 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1776 dump_enum_item(F, tp, i);
1777 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1782 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1790 break; /* case k_type */
1793 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1795 } /* switch kind_or_entity */
1798 typedef struct _h_env {
1803 /** For dumping class hierarchies.
1804 * Dumps a class type node and a superclass edge.
1805 * If env->dump_ent dumps entities of classes and overwrites edges.
1808 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1811 int i = 0; /* to shutup gcc */
1813 /* dump this type or entity */
1814 switch (get_kind(tore)) {
1816 entity *ent = (entity *)tore;
1817 if (get_entity_owner(ent) == get_glob_type()) break;
1818 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1819 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1821 dump_entity_node(F, ent, 0);
1823 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1824 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1825 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1827 } break; /* case k_entity */
1830 type *tp = (type *)tore;
1831 if (tp == get_glob_type()) break;
1832 switch (get_type_tpop_code(tp)) {
1834 print_type_node(F, tp);
1835 /* and now the edges */
1836 for (i=0; i < get_class_n_supertypes(tp); i++)
1838 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1844 break; /* case k_type */
1847 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1849 } /* switch kind_or_entity */
1852 /*******************************************************************/
1853 /* dump analysis information that is expressed in graph terms. */
1854 /*******************************************************************/
1856 /* dump out edges */
1858 dump_out_edge(ir_node *n, void *env) {
1861 for (i = 0; i < get_irn_n_outs(n); i++) {
1862 assert(get_irn_out(n, i));
1863 fprintf (F, "edge: {sourcename: \"");
1865 fprintf (F, "\" targetname: \"");
1866 PRINT_NODEID(get_irn_out(n, i));
1867 fprintf (F, "\" color: red linestyle: dashed");
1873 dump_loop_label(FILE *F, ir_loop *loop) {
1874 fprintf (F, "loop %d, %d sons, %d nodes",
1875 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1878 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1879 fprintf (F, " info1: \"");
1880 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1881 #if DEBUG_libfirm /* GL @@@ debug analyses */
1882 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1888 dump_loop_node(FILE *F, ir_loop *loop) {
1889 fprintf (F, "node: {title: \"");
1891 fprintf (F, "\" label: \"");
1892 dump_loop_label(F, loop);
1894 dump_loop_info(F, loop);
1900 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1902 fprintf (F, "edge: {sourcename: \"");
1904 fprintf (F, "\" targetname: \"");
1905 PRINT_NODEID(get_loop_node(loop, i));
1906 fprintf (F, "\" color: green");
1911 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1913 fprintf (F, "edge: {sourcename: \"");
1915 fprintf (F, "\" targetname: \"");
1916 PRINT_LOOPID(get_loop_son(loop, i));
1917 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1918 get_loop_element_pos(loop, get_loop_son(loop, i)));
1922 void dump_loops(FILE *F, ir_loop *loop) {
1924 /* dump this loop node */
1925 dump_loop_node(F, loop);
1927 /* dump edges to nodes in loop -- only if it is a real loop */
1928 if (get_loop_depth(loop) != 0) {
1929 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1930 dump_loop_node_edge(F, loop, i);
1933 for (i = 0; i < get_loop_n_sons(loop); i++) {
1934 dump_loops(F, get_loop_son(loop, i));
1935 dump_loop_son_edge(F, loop, i);
1940 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1941 ir_graph *rem = current_ir_graph;
1942 current_ir_graph = irg;
1944 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1946 current_ir_graph = rem;
1951 * dumps the VCG header
1953 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1962 if (!orientation) orientation = "bottom_to_top";
1966 "graph: { title: \"ir graph of %s\"\n"
1967 "display_edge_labels: %s\n"
1968 "layoutalgorithm: mindepth\n"
1969 "manhattan_edges: yes\n"
1970 "port_sharing: no\n"
1972 "classname 1: \"intrablock Data\"\n"
1973 "classname 16: \"interblock Data\"\n"
1974 "classname 2: \"Block\"\n"
1975 "classname 13: \"Control Flow\"\n"
1976 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1977 "classname 14: \"intrablock Memory\"\n"
1978 "classname 17: \"interblock Memory\"\n"
1979 "classname 15: \"Dominators\"\n"
1980 "classname 3: \"Entity type\"\n"
1981 "classname 4: \"Entity owner\"\n"
1982 "classname 5: \"Method Param\"\n"
1983 "classname 6: \"Method Res\"\n"
1984 "classname 7: \"Super\"\n"
1985 "classname 8: \"Union\"\n"
1986 "classname 9: \"Points-to\"\n"
1987 "classname 10: \"Array Element Type\"\n"
1988 "classname 11: \"Overwrites\"\n"
1989 "classname 12: \"Member\"\n"
1990 "infoname 1: \"Attribute\"\n"
1991 "infoname 2: \"Verification errors\"\n"
1992 "infoname 3: \"Debug info\"\n",
1993 name, label, orientation);
1995 /* don't use all, the range is too whith/black. */
1999 "colorentry 100: 0 0 0\n"
2000 "colorentry 101: 20 0 0\n"
2001 "colorentry 102: 40 0 0\n"
2002 "colorentry 103: 60 0 0\n"
2003 "colorentry 104: 80 0 0\n"
2004 "colorentry 105: 100 0 0\n"
2005 "colorentry 106: 120 0 0\n"
2006 "colorentry 107: 140 0 0\n"
2007 "colorentry 108: 150 0 0\n"
2008 "colorentry 109: 180 0 0\n"
2009 "colorentry 110: 200 0 0\n"
2010 "colorentry 111: 220 0 0\n"
2011 "colorentry 112: 240 0 0\n"
2012 "colorentry 113: 255 0 0\n"
2013 "colorentry 113: 255 20 20\n"
2014 "colorentry 114: 255 40 40\n"
2015 "colorentry 115: 255 60 60\n"
2016 "colorentry 116: 255 80 80\n"
2017 "colorentry 117: 255 100 100\n"
2018 "colorentry 118: 255 120 120\n"
2019 "colorentry 119: 255 140 140\n"
2020 "colorentry 120: 255 150 150\n"
2021 "colorentry 121: 255 180 180\n"
2022 "colorentry 122: 255 200 200\n"
2023 "colorentry 123: 255 220 220\n"
2024 "colorentry 124: 255 240 240\n"
2025 "colorentry 125: 255 250 250\n"
2028 fprintf (F, "\n"); /* a separator */
2034 * @param irg The graph to be dumped
2035 * @param suffix1 first filename suffix
2036 * @param suffix2 second filename suffix
2038 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
2040 const char *nm = get_irg_dump_name(irg);
2041 int len = strlen(nm), i, j;
2042 char *fname; /* filename to put the vcg information in */
2044 if (!suffix1) suffix1 = "";
2045 if (!suffix2) suffix2 = "";
2047 /* open file for vcg graph */
2048 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
2050 /* strncpy (fname, nm, len); */ /* copy the filename */
2052 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2054 fname[j] = '@'; j++; fname[j] = '1'; j++;
2055 } else if (nm[i] == '@') {
2056 fname[j] = '@'; j++; fname[j] = '2'; j++;
2058 fname[j] = nm[i]; j++;
2062 strcat (fname, suffix1); /* append file suffix */
2063 strcat (fname, suffix2); /* append file suffix */
2064 strcat (fname, ".vcg"); /* append the .vcg suffix */
2066 /* vcg really expect only a <CR> at end of line, so
2067 * the "b"inary mode is what you mean (and even needed for Win32)
2069 F = fopen (fname, "wb"); /* open file for writing */
2071 panic("cannot open %s for writing (%m)", fname); /* not reached */
2081 * @param irg The graph to be dumped
2082 * @param suffix filename suffix
2084 FILE *vcg_open_name (const char *name, const char *suffix) {
2086 char *fname; /* filename to put the vcg information in */
2087 int i, j, len = strlen(name);
2089 if (!suffix) suffix = "";
2091 /** open file for vcg graph */
2092 fname = malloc (len * 2 + 5 + strlen(suffix));
2093 /* strcpy (fname, name);*/ /* copy the filename */
2095 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
2096 if (name[i] == '/') {
2097 fname[j] = '@'; j++; fname[j] = '1'; j++;
2098 } else if (name[i] == '@') {
2099 fname[j] = '@'; j++; fname[j] = '2'; j++;
2101 fname[j] = name[i]; j++;
2105 strcat (fname, suffix);
2106 strcat (fname, ".vcg"); /* append the .vcg suffix */
2108 /* vcg really expect only a <CR> at end of line, so
2109 * the "b"inary mode is what you mean (and even needed for Win32)
2111 F = fopen (fname, "wb"); /* open file for writing */
2113 panic ("cannot open %s for writing (%m)", fname); /* not reached */
2121 * Dumps the vcg file footer
2123 static INLINE void dump_vcg_footer (FILE *F) {
2128 * close the vcg file
2130 void vcg_close (FILE *F) {
2131 dump_vcg_footer(F); /* print footer */
2132 fclose (F); /* close vcg file */
2135 /************************************************************************/
2136 /************************************************************************/
2137 /* Routines that dump all or parts of the firm representation to a file */
2138 /************************************************************************/
2139 /************************************************************************/
2141 /************************************************************************/
2142 /* Dump ir graphs, different formats and additional information. */
2143 /************************************************************************/
2145 /** Routine to dump a graph, blocks as conventional nodes. */
2147 dump_ir_graph (ir_graph *irg, const char *suffix )
2152 rem = current_ir_graph;
2154 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2156 current_ir_graph = irg;
2157 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2158 else suffix1 = "-pure";
2159 f = vcg_open(irg, suffix, suffix1);
2160 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2162 /* walk over the graph */
2163 /* dump_whole_node must be called in post visiting predecessors */
2164 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2166 /* dump the out edges in a separate walk */
2167 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2168 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2173 current_ir_graph = rem;
2176 /* Dump a firm graph without explicit block nodes. */
2177 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2183 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2186 if (get_interprocedural_view()) suffix1 = "-ip";
2188 f = vcg_open(irg, suffix, suffix1);
2189 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2191 construct_block_lists(irg);
2194 * If we are in the interprocedural view, we dump not
2195 * only the requested irg but also all irgs that can be reached
2198 for (i = 0; i < get_irp_n_irgs(); i++) {
2199 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2201 dump_graph_from_list(f, get_irp_irg(i));
2209 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2210 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2216 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2221 if (get_interprocedural_view()) suffix1 = "-ip";
2223 F = vcg_open(irg, suffix, suffix1);
2224 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2226 construct_extblock_lists(irg);
2228 fprintf(F, "graph: { title: \"");
2230 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2231 get_ent_dump_name(get_irg_entity(irg)));
2233 for (i = 0; i < get_irp_n_irgs(); i++) {
2234 ir_graph *irg = get_irp_irg(i);
2235 list_tuple *lists = ird_get_irg_link(irg);
2238 /* dump the extended blocks first */
2239 if (ARR_LEN(lists->extbb_list)) {
2240 ird_set_irg_link(irg, lists->extbb_list);
2241 dump_extblock_graph(F, irg);
2244 /* we may have blocks without extended blocks, bad for instance */
2245 if (ARR_LEN(lists->blk_list)) {
2246 ird_set_irg_link(irg, lists->blk_list);
2247 dump_block_graph(F, irg);
2250 DEL_ARR_F(lists->extbb_list);
2251 DEL_ARR_F(lists->blk_list);
2256 /* Close the vcg information for the irg */
2257 fprintf(F, "}\n\n");
2263 /* dumps a graph with type information */
2265 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2268 ir_graph *rem = current_ir_graph;
2271 /* if a filter is set, dump only the irg's that match the filter */
2272 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2275 current_ir_graph = irg;
2277 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2278 else suffix1 = "-pure-wtypes";
2279 f = vcg_open(irg,suffix, suffix1);
2280 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2282 /* dump common ir graph */
2283 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2284 /* dump type info */
2285 type_walk_irg(irg, dump_type_info, NULL, f);
2286 inc_irg_visited(get_const_code_irg());
2287 /* dump edges from graph to type info */
2288 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2291 current_ir_graph = rem;
2295 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2300 ir_graph *rem = current_ir_graph;
2302 /* if a filter is set, dump only the irg's that match the filter */
2303 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2306 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2307 else suffix1 = "-wtypes";
2308 f = vcg_open(irg, suffix, suffix1);
2309 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2311 /* dump common blocked ir graph */
2312 construct_block_lists(irg);
2314 for (i = 0; i < get_irp_n_irgs(); i++) {
2315 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2317 dump_graph_from_list(f, get_irp_irg(i));
2322 /* dump type info */
2323 current_ir_graph = irg;
2324 type_walk_irg(irg, dump_type_info, NULL, f);
2325 inc_irg_visited(get_const_code_irg());
2327 /* dump edges from graph to type info */
2328 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2330 current_ir_graph = rem;
2334 /*---------------------------------------------------------------------*/
2335 /* The following routines dump a control flow graph. */
2336 /*---------------------------------------------------------------------*/
2339 dump_block_to_cfg(ir_node *block, void *env) {
2344 if (is_Block(block)) {
2345 /* This is a block. Dump a node for the block. */
2346 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2347 fprintf (F, "\" label: \"");
2348 if (block == get_irg_start_block(get_irn_irg(block)))
2349 fprintf(F, "Start ");
2350 if (block == get_irg_end_block(get_irn_irg(block)))
2353 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2354 PRINT_NODEID(block);
2356 fprintf(F, "info1:\"");
2359 if (dump_dominator_information_flag) {
2360 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2361 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2362 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2365 /* show arity and possible Bad predecessors of the block */
2366 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2367 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2368 ir_node *pred = get_Block_cfgpred(block, i);
2371 fprintf(F, "Bad pred at pos: ");
2372 fprintf(F, "%d ", i);
2379 /* the generic version. */
2380 dump_irnode_to_file(F, block);
2382 /* Check whether we have bad predecessors to color the block. */
2383 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2384 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2388 fprintf (F, "\""); /* closing quote of info */
2390 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2391 (block == get_irg_end_block(get_irn_irg(block))) )
2392 fprintf(F, " color:blue ");
2394 fprintf(F, " color:yellow ");
2397 /* Dump the edges */
2398 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2399 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2400 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2401 fprintf (F, "edge: { sourcename: \"");
2402 PRINT_NODEID(block);
2403 fprintf (F, "\" targetname: \"");
2405 fprintf (F, "\"}\n");
2408 /* Dump dominator edge */
2409 if (dump_dominator_information_flag && get_Block_idom(block)) {
2410 pred = get_Block_idom(block);
2411 fprintf (F, "edge: { sourcename: \"");
2412 PRINT_NODEID(block);
2413 fprintf (F, "\" targetname: \"");
2415 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2421 dump_cfg (ir_graph *irg, const char *suffix)
2424 ir_graph *rem = current_ir_graph;
2425 int ddif = dump_dominator_information_flag;
2426 int ipv = get_interprocedural_view();
2428 /* if a filter is set, dump only the irg's that match the filter */
2429 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2432 current_ir_graph = irg;
2434 f = vcg_open(irg, suffix, "-cfg");
2435 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2438 printf("Warning: dumping cfg not in interprocedural view!\n");
2439 set_interprocedural_view(false);
2442 if (get_irg_dom_state(irg) != dom_consistent)
2443 dump_dominator_information_flag = 0;
2445 /* walk over the blocks in the graph */
2446 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2447 dump_node(f, get_irg_bad(irg));
2449 dump_dominator_information_flag = ddif;
2450 set_interprocedural_view(ipv);
2452 current_ir_graph = rem;
2456 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2457 if (pset_find_ptr(mark_set, n)) return;
2459 pset_insert_ptr(mark_set, n);
2462 int i, start = is_Block(n) ? 0 : -1;
2463 dump_whole_node(n, F);
2464 for (i = start; i < get_irn_arity(n); ++i)
2465 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2468 /* Don't dump edges to nodes further out. These might be edges to
2469 nodes we already dumped, if there is a shorter path to these. */
2473 static int subgraph_counter = 0;
2474 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2477 pset *mark_set = pset_new_ptr(1);
2478 sprintf(buf, "-subg_%03d", subgraph_counter++);
2479 F = vcg_open(get_irn_irg(root), suffix, buf);
2480 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2481 descend_and_dump(F, root, depth, mark_set);
2487 static int weight_overall(int rec, int loop) {
2488 return 2*rec + loop;
2491 static int compute_color (int my, int max) {
2498 /* if small, scale to the full color range. */
2500 my = my * (n_colors/max);
2502 step = 1 + (max / n_colors);
2506 return base_color + n_colors - color;
2509 static int get_entity_color(entity *ent) {
2510 ir_graph *irg = get_entity_irg(ent);
2514 int rec_depth = get_irg_recursion_depth(irg);
2515 int loop_depth = get_irg_loop_depth(irg);
2516 int overall_depth = weight_overall(rec_depth, loop_depth);
2518 int max_rec_depth = irp->max_callgraph_recursion_depth;
2519 int max_loop_depth = irp->max_callgraph_loop_depth;
2520 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2522 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2523 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2524 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2526 return my_overall_color;
2530 void dump_callgraph(const char *suffix) {
2532 int i, n_irgs = get_irp_n_irgs();
2533 int rem = edge_label;
2535 //ident *prefix = new_id_from_str("java/");
2537 F = vcg_open_name("Callgraph", suffix);
2538 dump_vcg_header(F, "Callgraph", NULL);
2540 for (i = 0; i < n_irgs; ++i) {
2541 ir_graph *irg = get_irp_irg(i);
2542 entity *ent = get_irg_entity(irg);
2543 int j, n_callees = get_irg_n_callees(irg);
2545 /* Do not dump runtime system. */
2546 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2548 dump_entity_node(F, ent, get_entity_color(ent));
2549 for (j = 0; j < n_callees; ++j) {
2550 entity *c = get_irg_entity(get_irg_callee(irg, j));
2551 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2552 int be = is_irg_callee_backedge(irg, j);
2555 "label:\"recursion %d\" color: %d" :
2556 "label:\"calls %d\" color: %d";
2557 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2565 /* Dump all irgs in interprocedural view to a single file. */
2566 void dump_all_cg_block_graph(const char *suffix) {
2569 int rem_view = get_interprocedural_view();
2570 set_interprocedural_view(true);
2572 f = vcg_open_name("All_graphs", suffix);
2573 dump_vcg_header(f, "All_graphs", NULL);
2575 /* collect nodes in all irgs reachable in call graph*/
2576 for (i = 0; i < get_irp_n_irgs(); i++)
2577 ird_set_irg_link(get_irp_irg(i), NULL);
2579 cg_walk(clear_link, collect_node, NULL);
2581 /* dump all graphs */
2582 for (i = 0; i < get_irp_n_irgs(); i++) {
2583 current_ir_graph = get_irp_irg(i);
2584 assert(ird_get_irg_link(current_ir_graph));
2585 dump_graph_from_list(f, current_ir_graph);
2586 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2590 set_interprocedural_view(rem_view);
2593 /*---------------------------------------------------------------------*/
2594 /* the following routines dumps type information without any ir nodes. */
2595 /*---------------------------------------------------------------------*/
2598 dump_type_graph (ir_graph *irg, const char *suffix)
2602 rem = current_ir_graph;
2604 /* if a filter is set, dump only the irg's that match the filter */
2605 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2607 current_ir_graph = irg;
2609 f = vcg_open(irg, suffix, "-type");
2610 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2612 /* walk over the blocks in the graph */
2613 type_walk_irg(irg, dump_type_info, NULL, f);
2614 /* The walker for the const code can be called several times for the
2615 same (sub) expression. So that no nodes are dumped several times
2616 we decrease the visited flag of the corresponding graph after each
2617 walk. So now increase it finally. */
2618 inc_irg_visited(get_const_code_irg());
2621 current_ir_graph = rem;
2625 dump_all_types (const char *suffix)
2627 FILE *f = vcg_open_name("All_types", suffix);
2628 dump_vcg_header(f, "All_types", NULL);
2629 type_walk(dump_type_info, NULL, f);
2630 inc_irg_visited(get_const_code_irg());
2635 dump_class_hierarchy (bool entities, const char *suffix)
2637 FILE *f = vcg_open_name("class_hierarchy", suffix);
2641 dump_vcg_header(f, "class_hierarchy", NULL);
2646 type_walk(dump_class_hierarchy_node, NULL, &env);
2650 /*---------------------------------------------------------------------*/
2651 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2653 /* dump_ir_block_graph */
2655 /* dump_type_graph */
2656 /* dump_ir_graph_w_types */
2657 /*---------------------------------------------------------------------*/
2659 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2660 int i, n_irgs = get_irp_n_irgs();
2661 for (i = 0; i < n_irgs; ++i) {
2662 dmp_grph(get_irp_irg(i), suffix);
2667 /*--------------------------------------------------------------------------------*
2668 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2669 * packed together in one subgraph/box *
2670 *--------------------------------------------------------------------------------*/
2672 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2673 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2675 ir_loop *son = NULL;
2677 /* Dump a new loop node. */
2678 dump_loop_node(F, loop);
2680 /* Dump the loop elements. */
2682 for(i = 0; i < get_loop_n_elements(loop); i++) {
2683 le = get_loop_element(loop, i);
2685 if (get_kind(son) == k_ir_loop) {
2687 /* We are a loop son -> Recurse */
2689 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2690 fprintf(F, "\" }\n");
2691 fprintf (F, "edge: {sourcename: \"");
2693 fprintf (F, "\" targetname: \"");
2695 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2696 loop_node_started = 0;
2698 dump_loop_son_edge(F, loop, son_number++);
2699 dump_loops_standalone(F, son);
2700 } else if (get_kind(son) == k_ir_node) {
2701 /* We are a loop node -> Collect firm nodes */
2703 ir_node *n = le.node;
2706 if (!loop_node_started) {
2707 /* Start a new node which contains all firm nodes of the current loop */
2708 fprintf (F, "node: { title: \"");
2710 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2711 loop_node_started = 1;
2717 bad |= dump_node_label(F, n);
2718 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2719 if (has_backedges(n)) fprintf(F, "\t loop head!");
2720 } else { /* for callgraph loop tree */
2722 assert(get_kind(son) == k_ir_graph);
2724 /* We are a loop node -> Collect firm graphs */
2725 n = (ir_graph *)le.node;
2726 if (!loop_node_started) {
2727 /* Start a new node which contains all firm nodes of the current loop */
2728 fprintf (F, "node: { title: \"");
2730 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2731 loop_node_started = 1;
2736 fprintf (F, " %s", get_irg_dump_name(n));
2737 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2741 if (loop_node_started) {
2742 fprintf(F, "\" }\n");
2743 fprintf (F, "edge: {sourcename: \"");
2745 fprintf (F, "\" targetname: \"");
2747 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2748 loop_node_started = 0;
2752 void dump_loop_tree(ir_graph *irg, const char *suffix)
2755 ir_graph *rem = current_ir_graph;
2756 int el_rem = edge_label;
2759 /* if a filter is set, dump only the irg's that match the filter */
2760 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2762 current_ir_graph = irg;
2764 f = vcg_open(irg, suffix, "-looptree");
2765 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2767 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2771 edge_label = el_rem;
2772 current_ir_graph = rem;
2775 void dump_callgraph_loop_tree(const char *suffix) {
2777 F = vcg_open_name("Callgraph_looptree", suffix);
2778 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2779 dump_loops_standalone(F, irp->outermost_cg_loop);
2784 /*-----------------------------------------------------------------------------*/
2785 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2786 /*-----------------------------------------------------------------------------*/
2788 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2789 int i, son_number = 0, node_number = 0;
2791 if (dump_loop_information_flag) dump_loop_node(F, loop);
2793 for (i = 0; i < get_loop_n_elements(loop); i++) {
2794 loop_element le = get_loop_element(loop, i);
2795 if (*(le.kind) == k_ir_loop) {
2796 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2798 collect_nodeloop(F, le.son, loopnodes);
2800 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2801 eset_insert(loopnodes, le.node);
2806 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2809 for(i = 0; i < get_loop_n_elements(loop); i++) {
2810 loop_element le = get_loop_element(loop, i);
2811 if (*(le.kind) == k_ir_loop) {
2813 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2815 if (is_Block(le.node)) start = 0; else start = -1;
2816 for (j = start; j < get_irn_arity(le.node); j++) {
2817 ir_node *pred = get_irn_n(le.node, j);
2818 if (!eset_contains(loopnodes, pred)) {
2819 eset_insert(extnodes, pred);
2820 if (!is_Block(pred)) {
2821 pred = get_nodes_block(pred);
2822 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2830 void dump_loop(ir_loop *l, const char *suffix) {
2833 eset *loopnodes = eset_create();
2834 eset *extnodes = eset_create();
2837 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2838 F = vcg_open_name (name, suffix);
2839 dump_vcg_header(F, name, NULL);
2841 /* collect all nodes to dump */
2842 collect_nodeloop(F, l, loopnodes);
2843 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2845 /* build block lists */
2846 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2847 set_irn_link(n, NULL);
2848 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2849 set_irn_link(n, NULL);
2850 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2852 b = get_nodes_block(n);
2853 set_irn_link(n, get_irn_link(b));
2856 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2858 b = get_nodes_block(n);
2859 set_irn_link(n, get_irn_link(b));
2863 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2865 fprintf(F, "graph: { title: \"");
2867 fprintf(F, "\" label: \"");
2868 dump_node_opcode(F, b);
2869 fprintf (F, " %ld", get_irn_node_nr(b));
2870 fprintf(F, "\" status:clustered color:yellow\n");
2872 /* dump the blocks edges */
2873 dump_ir_data_edges(F, b);
2875 /* dump the nodes that go into the block */
2876 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2877 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2879 overrule_nodecolor = NULL;
2880 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2883 /* Close the vcg information for the block */
2885 dump_const_node_local(F, b);
2888 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2890 fprintf(F, "graph: { title: \"");
2892 fprintf(F, "\" label: \"");
2893 dump_node_opcode(F, b);
2894 fprintf (F, " %ld", get_irn_node_nr(b));
2895 fprintf(F, "\" status:clustered color:lightblue\n");
2897 /* dump the nodes that go into the block */
2898 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2899 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2901 overrule_nodecolor = NULL;
2902 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2905 /* Close the vcg information for the block */
2907 dump_const_node_local(F, b);
2911 eset_destroy(loopnodes);
2912 eset_destroy(extnodes);