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));
692 * Dump additional node attributes of some nodes to a file F.
695 dump_node_nodeattr(FILE *F, ir_node *n)
700 switch (get_irn_opcode(n)) {
702 if (false && get_interprocedural_view()) {
703 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
707 pred = get_Proj_pred(n);
709 if (get_irn_opcode(pred) == iro_Cmp)
710 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
711 else if (get_irn_opcode(pred) == iro_Start) {
712 switch (get_Proj_proj(n)) {
713 case pn_Start_P_frame_base:
714 fprintf (F, "FrameBase "); break;
715 case pn_Start_P_globals:
716 fprintf (F, "GlobalBase "); break;
717 case pn_Start_P_value_arg_base:
718 fprintf (F, "ValueBase "); break;
720 fprintf (F, "%ld ", get_Proj_proj(n));
723 else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
724 fprintf (F, "Arg %ld ", get_Proj_proj(n));
726 fprintf (F, "%ld ", get_Proj_proj(n));
729 fprintf (F, "%ld ", get_Filter_proj(n));
732 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
735 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
738 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
749 #include "execution_frequency.h"
750 #include "callgraph.h"
752 void dump_node_ana_vals(FILE *F, ir_node *n) {
754 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
755 get_irn_exec_freq(n),
756 get_irg_method_execution_frequency(get_irn_irg(n)),
757 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
758 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
763 /* Dumps a node label without the enclosing ". */
764 int dump_node_label(FILE *F, ir_node *n) {
767 bad |= dump_node_opcode(F, n);
768 bad |= dump_node_mode(F, n);
770 bad |= dump_node_typeinfo(F, n);
771 bad |= dump_node_nodeattr(F, n);
772 fprintf(F, "%ld", get_irn_node_nr(n));
779 * Dumps the attributes of a node n into the file F.
780 * Currently this is only the color of a node.
782 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
787 fprintf(F, "color: red");
791 if (dump_node_vcgattr_hook)
792 if (dump_node_vcgattr_hook(F, node, local))
795 n = local ? local : node;
797 switch (get_irn_opcode(n)) {
804 fprintf (F, "color: blue");
807 if (is_Block_dead(n))
808 fprintf (F, "color: lightred");
810 fprintf (F, "color: lightyellow");
813 fprintf (F, "color: green");
819 fprintf (F, "color: yellow");
822 PRINT_DEFAULT_NODE_ATTR;
825 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
830 * Dump the node information of a node n to a file F.
832 static INLINE int dump_node_info(FILE *F, ir_node *n)
834 fprintf (F, " info1: \"");
835 bad = dump_irnode_to_file(F, n);
841 * checks whether a node is "constant-like" ie can be treated "block-less"
844 bool is_constlike_node(ir_node *n) {
845 ir_op *op = get_irn_op(n);
846 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
850 /** outputs the predecessors of n, that are constants, local. I.e.,
851 generates a copy of the constant predecessors for each node called with. */
852 static void dump_const_node_local(FILE *F, ir_node *n) {
854 if (!get_opt_dump_const_local()) return;
856 /* Use visited flag to avoid outputting nodes twice.
857 initialize it first. */
858 for (i = 0; i < get_irn_arity(n); i++) {
859 ir_node *con = get_irn_n(n, i);
860 if (is_constlike_node(con)) {
861 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
865 for (i = 0; i < get_irn_arity(n); i++) {
866 ir_node *con = get_irn_n(n, i);
867 if (is_constlike_node(con) && irn_not_visited(con)) {
870 mark_irn_visited(con);
871 /* Generate a new name for the node by appending the names of
873 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
874 fprintf(F, " label: \"");
875 bad |= dump_node_label(F, con);
877 bad |= dump_node_info(F, con);
878 dump_node_vcgattr(F, n, con, bad);
884 /** If the block of an edge is a const_like node, dump it local with an edge */
885 static void dump_const_block_local(FILE *F, ir_node *n) {
888 if (!get_opt_dump_const_local()) return;
890 blk = get_nodes_block(n);
891 if (is_constlike_node(blk)) {
894 /* Generate a new name for the node by appending the names of
896 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
897 fprintf(F, "\" label: \"");
898 bad |= dump_node_label(F, blk);
900 bad |= dump_node_info(F, blk);
901 dump_node_vcgattr(F, n, blk, bad);
904 fprintf (F, "edge: { sourcename: \"");
906 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
907 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
912 * prints the error message of a node to a file F as info2.
914 static void INLINE print_node_error(FILE *F, const char *err_msg)
919 fprintf (F, " info2: \"%s\"", err_msg);
923 * prints debug messages of a node to file F as info3.
925 static void print_node_dbg_info(FILE *F, dbg_info *dbg)
929 if (__dbg_info_snprint) {
931 if (__dbg_info_snprint(buf, sizeof(buf), dbg) > 0)
932 fprintf (F, " info3: \"%s\"", buf);
939 static void dump_node(FILE *F, ir_node *n)
944 if (get_opt_dump_const_local() && is_constlike_node(n))
948 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
950 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
951 bad |= dump_node_label(F, n);
952 dump_node_ana_vals(F, n);
953 //dump_node_ana_info(F, n);
955 bad |= dump_node_info(F, n);
956 print_node_error(F, p);
957 print_node_dbg_info(F, get_irn_dbg_info(n));
958 dump_node_vcgattr(F, n, NULL, bad);
960 dump_const_node_local(F, n);
962 if(dump_node_edge_hook)
963 dump_node_edge_hook(F, n);
965 dump_irn_chi_term(F, n);
966 dump_irn_state(F, n);
970 /** dump the edge to the block this node belongs to */
972 dump_ir_block_edge(FILE *F, ir_node *n) {
973 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
974 if (is_no_Block(n)) {
975 ir_node *block = get_nodes_block(n);
977 if (get_opt_dump_const_local() && is_constlike_node(block)) {
978 dump_const_block_local(F, n);
981 fprintf (F, "edge: { sourcename: \"");
983 fprintf (F, "\" targetname: ");
984 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
985 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
991 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
993 * do not use get_nodes_block() here, will fail
994 * if the irg is not pinned.
996 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
997 fprintf (F, INTRA_DATA_EDGE_ATTR);
999 fprintf (F, INTER_DATA_EDGE_ATTR);
1003 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
1005 * do not use get_nodes_block() here, will fail
1006 * if the irg is not pinned.
1008 if (get_irn_n(from, -1) == get_irn_n(get_irn_n(from, to), -1))
1009 fprintf (F, INTRA_MEM_EDGE_ATTR);
1011 fprintf (F, INTER_MEM_EDGE_ATTR);
1015 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
1018 if (dump_backedge_information_flag && is_backedge(from, to))
1019 fprintf (F, BACK_EDGE_ATTR);
1021 switch (get_irn_opcode(from)) {
1023 fprintf (F, CF_EDGE_ATTR);
1025 case iro_Start: break;
1028 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
1029 fprintf (F, CF_EDGE_ATTR);
1030 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
1031 fprintf (F, INTER_MEM_EDGE_ATTR);
1039 print_data_edge_vcgattr(F, from, to);
1044 print_mem_edge_vcgattr(F, from, to);
1046 print_data_edge_vcgattr(F, from, to);
1050 print_data_edge_vcgattr(F, from, to);
1055 print_mem_edge_vcgattr(F, from, to);
1057 print_data_edge_vcgattr(F, from, to);
1064 print_data_edge_vcgattr(F, from, to);
1071 print_mem_edge_vcgattr(F, from, to);
1073 print_data_edge_vcgattr(F, from, to);
1085 print_data_edge_vcgattr(F, from, to);
1088 if (get_irn_modecode(from) == irm_M)
1089 fprintf (F, INTER_MEM_EDGE_ATTR);
1091 print_data_edge_vcgattr(F, from, to);
1098 print_mem_edge_vcgattr(F, from, to);
1100 print_data_edge_vcgattr(F, from, to);
1103 print_mem_edge_vcgattr(F, from, to);
1105 case iro_Tuple: break;
1108 switch (get_irn_modecode(from)) {
1110 fprintf (F, CF_EDGE_ATTR);
1113 fprintf (F, INTER_MEM_EDGE_ATTR);
1116 print_data_edge_vcgattr(F, from, to);
1120 case iro_Bad: break;
1121 case iro_Unknown: break;
1123 switch (get_irn_modecode(from)) {
1125 fprintf (F, INTRA_MEM_EDGE_ATTR);
1128 fprintf (F, CF_EDGE_ATTR);
1131 print_data_edge_vcgattr(F, from, to);
1139 /* dump edges to our inputs */
1141 dump_ir_data_edges(FILE *F, ir_node *n) {
1143 unsigned long visited = get_irn_visited(n);
1145 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1148 for (i = 0; i < get_irn_arity(n); i++) {
1149 ir_node * pred = get_irn_n(n, i);
1152 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1153 continue; /* pred not dumped */
1155 if (dump_backedge_information_flag && is_backedge(n, i))
1156 fprintf (F, "backedge: {sourcename: \"");
1158 fprintf (F, "edge: {sourcename: \"");
1160 fprintf (F, "\" targetname: ");
1161 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1162 PRINT_CONSTID(n, pred);
1164 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1166 fprintf (F, " label: \"%d\" ", i);
1167 print_edge_vcgattr(F, n, i);
1172 /** Dumps a node and its edges but not the block edge
1175 dump_node_wo_blockedge (ir_node *n, void *env) {
1178 dump_ir_data_edges(F, n);
1181 /** Dumps a node and its edges.
1184 dump_whole_node (ir_node *n, void *env) {
1186 dump_node_wo_blockedge(n, env);
1187 if (!node_floats(n)) dump_ir_block_edge(F, n);
1191 dump_const_node(ir_node *n, void *env) {
1192 if (is_Block(n)) return;
1193 dump_node_wo_blockedge(n, env);
1196 /***********************************************************************/
1197 /* the following routines dump the nodes/irgs bracketed to graphs. */
1198 /***********************************************************************/
1200 /** Dumps a constant expression as entity initializer, array bound ...
1202 static void dump_const_expression(FILE *F, ir_node *value) {
1203 ir_graph *rem = current_ir_graph;
1204 int rem_dump_const_local = dump_const_local;
1205 dump_const_local = 0;
1206 current_ir_graph = get_const_code_irg();
1207 irg_walk(value, dump_const_node, NULL, F);
1208 /* Decrease visited flag so that we walk with the same flag for the next
1209 expression. This guarantees that we don't dump the same node twice,
1210 as for const expressions cse is performed to save memory. */
1211 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1212 current_ir_graph = rem;
1213 dump_const_local = rem_dump_const_local;
1216 /** Dump a block as graph containing its nodes.
1218 * Expects to find nodes belonging to the block as list in its
1220 * Dumps the edges of all nodes including itself. */
1222 dump_whole_block(FILE *F, ir_node *block) {
1224 assert(is_Block(block));
1226 fprintf(F, "graph: { title: \"");
1227 PRINT_NODEID(block);
1228 fprintf(F, "\" label: \"");
1229 dump_node_label(F, block);
1231 if (get_opt_dump_abstvals())
1232 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1234 fprintf(F, "\" status:clustered color:%s \n",
1235 get_Block_matured(block) ? "yellow" : "red");
1237 /* dump the blocks edges */
1238 dump_ir_data_edges(F, block);
1240 /* dump the nodes that go into the block */
1241 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1243 dump_ir_data_edges(F, node);
1246 /* Close the vcg information for the block */
1248 dump_const_node_local(F, block);
1250 dump_irn_chi_term(F, block);
1255 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1256 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1258 dump_block_graph(FILE *F, ir_graph *irg) {
1260 ir_graph *rem = current_ir_graph;
1261 ir_node **arr = ird_get_irg_link(irg);
1262 current_ir_graph = irg;
1264 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1265 ir_node * node = arr[i];
1266 if (is_Block(node)) {
1267 /* Dumps the block and all the nodes in the block, which are to
1268 be found in Block->link. */
1269 dump_whole_block(F, node);
1271 /* Nodes that are not in a Block. */
1273 if (!node_floats(node) && is_Bad(get_nodes_block(node))) {
1274 dump_const_block_local(F, node);
1276 dump_ir_data_edges(F, node);
1280 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1281 dump_loop_nodes_into_graph(F, irg);
1283 current_ir_graph = rem;
1286 /** Dumps an irg as a graph clustered by block nodes.
1287 * If interprocedural view edges can point to nodes out of this graph.
1289 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1291 fprintf(F, "graph: { title: \"");
1293 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1294 get_ent_dump_name(get_irg_entity(irg)));
1296 dump_block_graph(F, irg);
1298 /* Close the vcg information for the irg */
1299 fprintf(F, "}\n\n");
1302 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1303 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1305 dump_extblock_graph(FILE *F, ir_graph *irg) {
1307 ir_graph *rem = current_ir_graph;
1308 ir_extblk **arr = ird_get_irg_link(irg);
1309 current_ir_graph = irg;
1312 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1313 ir_extblk *extbb = arr[i];
1314 ir_node *leader = extbb->blks[0];
1317 fprintf(F, "graph: { title: \"");
1318 PRINT_EXTBBID(leader);
1319 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1320 get_irn_node_nr(leader));
1322 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1323 ir_node * node = extbb->blks[j];
1324 if (is_Block(node)) {
1325 /* Dumps the block and all the nodes in the block, which are to
1326 be found in Block->link. */
1327 dump_whole_block(F, node);
1329 /* Nodes that are not in a Block. */
1331 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1332 dump_const_block_local(F, node);
1334 dump_ir_data_edges(F, node);
1340 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1341 dump_loop_nodes_into_graph(F, irg);
1343 current_ir_graph = rem;
1348 /*******************************************************************/
1349 /* Basic type and entity nodes and edges. */
1350 /*******************************************************************/
1352 /** dumps the edges between nodes and their type or entity attributes. */
1353 static void dump_node2type_edges(ir_node *n, void *env)
1358 switch (get_irn_opcode(n)) {
1360 /* @@@ some consts have an entity */
1363 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1364 || (get_SymConst_kind(n) ==symconst_size))
1366 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1370 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1373 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1376 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1379 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1382 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1390 static int print_type_info(FILE *F, type *tp) {
1393 if (get_type_state(tp) == layout_undefined) {
1394 fprintf(F, "state: layout_undefined\n");
1396 fprintf(F, "state: layout_fixed,\n");
1398 if (get_type_mode(tp))
1399 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1400 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1405 static void print_typespecific_info(FILE *F, type *tp) {
1406 switch (get_type_tpop_code(tp)) {
1409 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1416 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1417 fprintf(F, "params: %d\n", get_method_n_params(tp));
1418 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1426 case tpo_enumeration:
1440 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1441 switch (get_type_tpop_code(tp)) {
1444 if (peculiarity_existent == get_class_peculiarity(tp))
1445 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1447 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1451 fprintf (F, " " TYPE_METH_NODE_ATTR);
1462 case tpo_enumeration:
1476 /* Why not dump_type_node as the others? */
1477 static int print_type_node(FILE *F, type *tp)
1481 fprintf (F, "node: {title: ");
1483 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1484 fprintf (F, " info1: \"");
1486 bad |= print_type_info(F, tp);
1487 print_typespecific_info(F, tp);
1489 dump_type_to_file(F, tp, dump_verbosity_max);
1492 print_typespecific_vcgattr(F, tp);
1498 int dump_type_node(FILE *F, type *tp) {
1499 return print_type_node(F, tp);
1503 #define X(a) case a: fprintf(F, #a); break
1504 void dump_entity_node(FILE *F, entity *ent, int color)
1506 fprintf (F, "node: {title: \"");
1507 PRINT_ENTID(ent); fprintf(F, "\"");
1508 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1509 fprintf (F, "label: ");
1510 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1512 fprintf(F, "color: %d", color);
1514 fprintf (F, ENTITY_NODE_ATTR);
1515 fprintf (F, "\n info1: \"");
1517 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1519 fprintf(F, "\"\n}\n");
1523 static void dump_enum_item(FILE *F, type *tp, int pos)
1526 ident *id = get_enumeration_nameid(tp, pos);
1527 tarval *tv = get_enumeration_enum(tp, pos);
1529 tarval_snprintf(buf, sizeof(buf), tv);
1530 fprintf (F, "node: {title: \"");
1531 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1532 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1533 fprintf (F, "label: ");
1534 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1535 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1538 /* dumps a type or entity and it's edges. */
1540 dump_type_info(type_or_ent *tore, void *env) {
1542 int i = 0; /* to shutup gcc */
1544 /* dump this type or entity */
1546 switch (get_kind(tore)) {
1549 entity *ent = (entity *)tore;
1552 dump_entity_node(F, ent, 0);
1554 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1555 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1556 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1557 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1558 if (is_Class_type(get_entity_owner(ent))) {
1559 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1560 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1562 /* attached subgraphs */
1563 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1564 if (is_atomic_entity(ent)) {
1565 value = get_atomic_ent_value(ent);
1567 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1568 /* DDMN(value); $$$ */
1569 dump_const_expression(F, value);
1572 if (is_compound_entity(ent)) {
1573 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1574 value = get_compound_ent_value(ent, i);
1576 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1577 dump_const_expression(F, value);
1578 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1580 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1581 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1582 get_compound_ent_value_member(ent, i), i);
1591 type *tp = (type *)tore;
1592 print_type_node(F, tp);
1593 /* and now the edges */
1594 switch (get_type_tpop_code(tp)) {
1597 for (i=0; i < get_class_n_supertypes(tp); i++)
1598 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1599 for (i=0; i < get_class_n_members(tp); i++)
1600 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1604 for (i=0; i < get_struct_n_members(tp); i++)
1605 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1609 for (i = 0; i < get_method_n_params(tp); i++)
1610 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1611 for (i = 0; i < get_method_n_ress(tp); i++)
1612 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1616 for (i = 0; i < get_union_n_members(tp); i++)
1617 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1621 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1622 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1623 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1624 ir_node *upper = get_array_upper_bound(tp, i);
1625 ir_node *lower = get_array_lower_bound(tp, i);
1626 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1627 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1628 dump_const_expression(F, upper);
1629 dump_const_expression(F, lower);
1633 case tpo_enumeration:
1635 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1636 dump_enum_item(F, tp, i);
1637 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1642 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1650 break; /* case k_type */
1653 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1655 } /* switch kind_or_entity */
1658 typedef struct _h_env {
1663 /** For dumping class hierarchies.
1664 * Dumps a class type node and a superclass edge.
1665 * If env->dump_ent dumps entities of classes and overwrites edges.
1668 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1671 int i = 0; /* to shutup gcc */
1673 /* dump this type or entity */
1674 switch (get_kind(tore)) {
1676 entity *ent = (entity *)tore;
1677 if (get_entity_owner(ent) == get_glob_type()) break;
1678 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1679 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1681 dump_entity_node(F, ent, 0);
1683 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1684 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1685 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1687 } break; /* case k_entity */
1690 type *tp = (type *)tore;
1691 if (tp == get_glob_type()) break;
1692 switch (get_type_tpop_code(tp)) {
1694 print_type_node(F, tp);
1695 /* and now the edges */
1696 for (i=0; i < get_class_n_supertypes(tp); i++)
1698 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1704 break; /* case k_type */
1707 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1709 } /* switch kind_or_entity */
1712 /*******************************************************************/
1713 /* dump analysis information that is expressed in graph terms. */
1714 /*******************************************************************/
1716 /* dump out edges */
1718 dump_out_edge(ir_node *n, void *env) {
1721 for (i = 0; i < get_irn_n_outs(n); i++) {
1722 assert(get_irn_out(n, i));
1723 fprintf (F, "edge: {sourcename: \"");
1725 fprintf (F, "\" targetname: \"");
1726 PRINT_NODEID(get_irn_out(n, i));
1727 fprintf (F, "\" color: red linestyle: dashed");
1733 dump_loop_label(FILE *F, ir_loop *loop) {
1734 fprintf (F, "loop %d, %d sons, %d nodes",
1735 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1738 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1739 fprintf (F, " info1: \"");
1740 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1741 #if DEBUG_libfirm /* GL @@@ debug analyses */
1742 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1748 dump_loop_node(FILE *F, ir_loop *loop) {
1749 fprintf (F, "node: {title: \"");
1751 fprintf (F, "\" label: \"");
1752 dump_loop_label(F, loop);
1754 dump_loop_info(F, loop);
1760 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1762 fprintf (F, "edge: {sourcename: \"");
1764 fprintf (F, "\" targetname: \"");
1765 PRINT_NODEID(get_loop_node(loop, i));
1766 fprintf (F, "\" color: green");
1771 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1773 fprintf (F, "edge: {sourcename: \"");
1775 fprintf (F, "\" targetname: \"");
1776 PRINT_LOOPID(get_loop_son(loop, i));
1777 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1778 get_loop_element_pos(loop, get_loop_son(loop, i)));
1782 void dump_loops(FILE *F, ir_loop *loop) {
1784 /* dump this loop node */
1785 dump_loop_node(F, loop);
1787 /* dump edges to nodes in loop -- only if it is a real loop */
1788 if (get_loop_depth(loop) != 0) {
1789 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1790 dump_loop_node_edge(F, loop, i);
1793 for (i = 0; i < get_loop_n_sons(loop); i++) {
1794 dump_loops(F, get_loop_son(loop, i));
1795 dump_loop_son_edge(F, loop, i);
1800 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1801 ir_graph *rem = current_ir_graph;
1802 current_ir_graph = irg;
1804 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1806 current_ir_graph = rem;
1811 * dumps the VCG header
1813 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1822 if (!orientation) orientation = "bottom_to_top";
1826 "graph: { title: \"ir graph of %s\"\n"
1827 "display_edge_labels: %s\n"
1828 "layoutalgorithm: mindepth\n"
1829 "manhattan_edges: yes\n"
1830 "port_sharing: no\n"
1832 "classname 1: \"intrablock Data\"\n"
1833 "classname 16: \"interblock Data\"\n"
1834 "classname 2: \"Block\"\n"
1835 "classname 13: \"Control Flow\"\n"
1836 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1837 "classname 14: \"intrablock Memory\"\n"
1838 "classname 17: \"interblock Memory\"\n"
1839 "classname 15: \"Dominators\"\n"
1840 "classname 3: \"Entity type\"\n"
1841 "classname 4: \"Entity owner\"\n"
1842 "classname 5: \"Method Param\"\n"
1843 "classname 6: \"Method Res\"\n"
1844 "classname 7: \"Super\"\n"
1845 "classname 8: \"Union\"\n"
1846 "classname 9: \"Points-to\"\n"
1847 "classname 10: \"Array Element Type\"\n"
1848 "classname 11: \"Overwrites\"\n"
1849 "classname 12: \"Member\"\n"
1850 "infoname 1: \"Attribute\"\n"
1851 "infoname 2: \"Verification errors\"\n"
1852 "infoname 3: \"Debug info\"\n",
1853 name, label, orientation);
1855 /* don't use all, the range is too whith/black. */
1859 "colorentry 100: 0 0 0\n"
1860 "colorentry 101: 20 0 0\n"
1861 "colorentry 102: 40 0 0\n"
1862 "colorentry 103: 60 0 0\n"
1863 "colorentry 104: 80 0 0\n"
1864 "colorentry 105: 100 0 0\n"
1865 "colorentry 106: 120 0 0\n"
1866 "colorentry 107: 140 0 0\n"
1867 "colorentry 108: 150 0 0\n"
1868 "colorentry 109: 180 0 0\n"
1869 "colorentry 110: 200 0 0\n"
1870 "colorentry 111: 220 0 0\n"
1871 "colorentry 112: 240 0 0\n"
1872 "colorentry 113: 255 0 0\n"
1873 "colorentry 113: 255 20 20\n"
1874 "colorentry 114: 255 40 40\n"
1875 "colorentry 115: 255 60 60\n"
1876 "colorentry 116: 255 80 80\n"
1877 "colorentry 117: 255 100 100\n"
1878 "colorentry 118: 255 120 120\n"
1879 "colorentry 119: 255 140 140\n"
1880 "colorentry 120: 255 150 150\n"
1881 "colorentry 121: 255 180 180\n"
1882 "colorentry 122: 255 200 200\n"
1883 "colorentry 123: 255 220 220\n"
1884 "colorentry 124: 255 240 240\n"
1885 "colorentry 125: 255 250 250\n"
1888 fprintf (F, "\n"); /* a separator */
1894 * @param irg The graph to be dumped
1895 * @param suffix1 first filename suffix
1896 * @param suffix2 second filename suffix
1898 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1900 const char *nm = get_irg_dump_name(irg);
1901 int len = strlen(nm), i, j;
1902 char *fname; /* filename to put the vcg information in */
1904 if (!suffix1) suffix1 = "";
1905 if (!suffix2) suffix2 = "";
1907 /* open file for vcg graph */
1908 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1910 /* strncpy (fname, nm, len); */ /* copy the filename */
1912 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1914 fname[j] = '@'; j++; fname[j] = '1'; j++;
1915 } else if (nm[i] == '@') {
1916 fname[j] = '@'; j++; fname[j] = '2'; j++;
1918 fname[j] = nm[i]; j++;
1922 strcat (fname, suffix1); /* append file suffix */
1923 strcat (fname, suffix2); /* append file suffix */
1924 strcat (fname, ".vcg"); /* append the .vcg suffix */
1926 /* vcg really expect only a <CR> at end of line, so
1927 * the "b"inary mode is what you mean (and even needed for Win32)
1929 F = fopen (fname, "wb"); /* open file for writing */
1931 panic("cannot open %s for writing (%m)", fname); /* not reached */
1941 * @param irg The graph to be dumped
1942 * @param suffix filename suffix
1944 FILE *vcg_open_name (const char *name, const char *suffix) {
1946 char *fname; /* filename to put the vcg information in */
1947 int i, j, len = strlen(name);
1949 if (!suffix) suffix = "";
1951 /** open file for vcg graph */
1952 fname = malloc (len * 2 + 5 + strlen(suffix));
1953 /* strcpy (fname, name);*/ /* copy the filename */
1955 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1956 if (name[i] == '/') {
1957 fname[j] = '@'; j++; fname[j] = '1'; j++;
1958 } else if (name[i] == '@') {
1959 fname[j] = '@'; j++; fname[j] = '2'; j++;
1961 fname[j] = name[i]; j++;
1965 strcat (fname, suffix);
1966 strcat (fname, ".vcg"); /* append the .vcg suffix */
1968 /* vcg really expect only a <CR> at end of line, so
1969 * the "b"inary mode is what you mean (and even needed for Win32)
1971 F = fopen (fname, "wb"); /* open file for writing */
1973 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1981 * Dumps the vcg file footer
1983 static INLINE void dump_vcg_footer (FILE *F) {
1988 * close the vcg file
1990 void vcg_close (FILE *F) {
1991 dump_vcg_footer(F); /* print footer */
1992 fclose (F); /* close vcg file */
1995 /************************************************************************/
1996 /************************************************************************/
1997 /* Routines that dump all or parts of the firm representation to a file */
1998 /************************************************************************/
1999 /************************************************************************/
2001 /************************************************************************/
2002 /* Dump ir graphs, different formats and additional information. */
2003 /************************************************************************/
2005 /** Routine to dump a graph, blocks as conventional nodes. */
2007 dump_ir_graph (ir_graph *irg, const char *suffix )
2012 rem = current_ir_graph;
2014 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2016 current_ir_graph = irg;
2017 if (get_interprocedural_view()) suffix1 = "-pure-ip";
2018 else suffix1 = "-pure";
2019 f = vcg_open(irg, suffix, suffix1);
2020 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2022 /* walk over the graph */
2023 /* dump_whole_node must be called in post visiting predecessors */
2024 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2026 /* dump the out edges in a separate walk */
2027 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
2028 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
2033 current_ir_graph = rem;
2036 /* Dump a firm graph without explicit block nodes. */
2037 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
2043 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2046 if (get_interprocedural_view()) suffix1 = "-ip";
2048 f = vcg_open(irg, suffix, suffix1);
2049 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2051 construct_block_lists(irg);
2054 * If we are in the interprocedural view, we dump not
2055 * only the requested irg but also all irgs that can be reached
2058 for (i = 0; i < get_irp_n_irgs(); i++) {
2059 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2061 dump_graph_from_list(f, get_irp_irg(i));
2069 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2070 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2076 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2081 if (get_interprocedural_view()) suffix1 = "-ip";
2083 F = vcg_open(irg, suffix, suffix1);
2084 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2086 construct_extblock_lists(irg);
2088 fprintf(F, "graph: { title: \"");
2090 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2091 get_ent_dump_name(get_irg_entity(irg)));
2093 for (i = 0; i < get_irp_n_irgs(); i++) {
2094 ir_graph *irg = get_irp_irg(i);
2095 list_tuple *lists = ird_get_irg_link(irg);
2098 /* dump the extended blocks first */
2099 if (ARR_LEN(lists->extbb_list)) {
2100 ird_set_irg_link(irg, lists->extbb_list);
2101 dump_extblock_graph(F, irg);
2104 /* we may have blocks without extended blocks, bad for instance */
2105 if (ARR_LEN(lists->blk_list)) {
2106 ird_set_irg_link(irg, lists->blk_list);
2107 dump_block_graph(F, irg);
2110 DEL_ARR_F(lists->extbb_list);
2111 DEL_ARR_F(lists->blk_list);
2116 /* Close the vcg information for the irg */
2117 fprintf(F, "}\n\n");
2123 /* dumps a graph with type information */
2125 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2128 ir_graph *rem = current_ir_graph;
2131 /* if a filter is set, dump only the irg's that match the filter */
2132 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2135 current_ir_graph = irg;
2137 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2138 else suffix1 = "-pure-wtypes";
2139 f = vcg_open(irg,suffix, suffix1);
2140 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2142 /* dump common ir graph */
2143 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2144 /* dump type info */
2145 type_walk_irg(irg, dump_type_info, NULL, f);
2146 inc_irg_visited(get_const_code_irg());
2147 /* dump edges from graph to type info */
2148 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2151 current_ir_graph = rem;
2155 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2160 ir_graph *rem = current_ir_graph;
2162 /* if a filter is set, dump only the irg's that match the filter */
2163 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2166 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2167 else suffix1 = "-wtypes";
2168 f = vcg_open(irg, suffix, suffix1);
2169 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2171 /* dump common blocked ir graph */
2172 construct_block_lists(irg);
2174 for (i = 0; i < get_irp_n_irgs(); i++) {
2175 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2177 dump_graph_from_list(f, get_irp_irg(i));
2182 /* dump type info */
2183 current_ir_graph = irg;
2184 type_walk_irg(irg, dump_type_info, NULL, f);
2185 inc_irg_visited(get_const_code_irg());
2187 /* dump edges from graph to type info */
2188 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2190 current_ir_graph = rem;
2194 /*---------------------------------------------------------------------*/
2195 /* The following routines dump a control flow graph. */
2196 /*---------------------------------------------------------------------*/
2199 dump_block_to_cfg(ir_node *block, void *env) {
2204 if (is_Block(block)) {
2205 /* This is a block. Dump a node for the block. */
2206 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2207 fprintf (F, "\" label: \"");
2208 if (block == get_irg_start_block(get_irn_irg(block)))
2209 fprintf(F, "Start ");
2210 if (block == get_irg_end_block(get_irn_irg(block)))
2213 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2214 PRINT_NODEID(block);
2216 fprintf(F, "info1:\"");
2219 if (dump_dominator_information_flag) {
2220 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2221 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2222 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2225 /* show arity and possible Bad predecessors of the block */
2226 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2227 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2228 ir_node *pred = get_Block_cfgpred(block, i);
2231 fprintf(F, "Bad pred at pos: ");
2232 fprintf(F, "%d ", i);
2239 /* the generic version. */
2240 dump_irnode_to_file(F, block);
2242 /* Check whether we have bad predecessors to color the block. */
2243 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2244 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2248 fprintf (F, "\""); /* closing quote of info */
2250 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2251 (block == get_irg_end_block(get_irn_irg(block))) )
2252 fprintf(F, " color:blue ");
2254 fprintf(F, " color:yellow ");
2257 /* Dump the edges */
2258 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2259 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2260 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2261 fprintf (F, "edge: { sourcename: \"");
2262 PRINT_NODEID(block);
2263 fprintf (F, "\" targetname: \"");
2265 fprintf (F, "\"}\n");
2268 /* Dump dominator edge */
2269 if (dump_dominator_information_flag && get_Block_idom(block)) {
2270 pred = get_Block_idom(block);
2271 fprintf (F, "edge: { sourcename: \"");
2272 PRINT_NODEID(block);
2273 fprintf (F, "\" targetname: \"");
2275 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2281 dump_cfg (ir_graph *irg, const char *suffix)
2284 ir_graph *rem = current_ir_graph;
2285 int ddif = dump_dominator_information_flag;
2286 int ipv = get_interprocedural_view();
2288 /* if a filter is set, dump only the irg's that match the filter */
2289 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2292 current_ir_graph = irg;
2294 f = vcg_open(irg, suffix, "-cfg");
2295 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2298 printf("Warning: dumping cfg not in interprocedural view!\n");
2299 set_interprocedural_view(false);
2302 if (get_irg_dom_state(irg) != dom_consistent)
2303 dump_dominator_information_flag = 0;
2305 /* walk over the blocks in the graph */
2306 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2307 dump_node(f, get_irg_bad(irg));
2309 dump_dominator_information_flag = ddif;
2310 set_interprocedural_view(ipv);
2312 current_ir_graph = rem;
2316 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2317 if (pset_find_ptr(mark_set, n)) return;
2319 pset_insert_ptr(mark_set, n);
2322 int i, start = is_Block(n) ? 0 : -1;
2323 dump_whole_node(n, F);
2324 for (i = start; i < get_irn_arity(n); ++i)
2325 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2328 /* Don't dump edges to nodes further out. These might be edges to
2329 nodes we already dumped, if there is a shorter path to these. */
2333 static int subgraph_counter = 0;
2334 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2337 pset *mark_set = pset_new_ptr(1);
2338 sprintf(buf, "-subg_%03d", subgraph_counter++);
2339 F = vcg_open(get_irn_irg(root), suffix, buf);
2340 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2341 descend_and_dump(F, root, depth, mark_set);
2347 static int weight_overall(int rec, int loop) {
2348 return 2*rec + loop;
2351 static int compute_color (int my, int max) {
2358 /* if small, scale to the full color range. */
2360 my = my * (n_colors/max);
2362 step = 1 + (max / n_colors);
2366 return base_color + n_colors - color;
2369 static int get_entity_color(entity *ent) {
2370 ir_graph *irg = get_entity_irg(ent);
2374 int rec_depth = get_irg_recursion_depth(irg);
2375 int loop_depth = get_irg_loop_depth(irg);
2376 int overall_depth = weight_overall(rec_depth, loop_depth);
2378 int max_rec_depth = irp->max_callgraph_recursion_depth;
2379 int max_loop_depth = irp->max_callgraph_loop_depth;
2380 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2382 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2383 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2384 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2386 return my_overall_color;
2390 void dump_callgraph(const char *suffix) {
2392 int i, n_irgs = get_irp_n_irgs();
2393 int rem = edge_label;
2395 //ident *prefix = new_id_from_str("java/");
2397 F = vcg_open_name("Callgraph", suffix);
2398 dump_vcg_header(F, "Callgraph", NULL);
2400 for (i = 0; i < n_irgs; ++i) {
2401 ir_graph *irg = get_irp_irg(i);
2402 entity *ent = get_irg_entity(irg);
2403 int j, n_callees = get_irg_n_callees(irg);
2405 /* Do not dump runtime system. */
2406 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2408 dump_entity_node(F, ent, get_entity_color(ent));
2409 for (j = 0; j < n_callees; ++j) {
2410 entity *c = get_irg_entity(get_irg_callee(irg, j));
2411 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2412 int be = is_irg_callee_backedge(irg, j);
2415 "label:\"recursion %d\" color: %d" :
2416 "label:\"calls %d\" color: %d";
2417 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2425 /* Dump all irgs in interprocedural view to a single file. */
2426 void dump_all_cg_block_graph(const char *suffix) {
2429 int rem_view = get_interprocedural_view();
2430 set_interprocedural_view(true);
2432 f = vcg_open_name("All_graphs", suffix);
2433 dump_vcg_header(f, "All_graphs", NULL);
2435 /* collect nodes in all irgs reachable in call graph*/
2436 for (i = 0; i < get_irp_n_irgs(); i++)
2437 ird_set_irg_link(get_irp_irg(i), NULL);
2439 cg_walk(clear_link, collect_node, NULL);
2441 /* dump all graphs */
2442 for (i = 0; i < get_irp_n_irgs(); i++) {
2443 current_ir_graph = get_irp_irg(i);
2444 assert(ird_get_irg_link(current_ir_graph));
2445 dump_graph_from_list(f, current_ir_graph);
2446 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2450 set_interprocedural_view(rem_view);
2453 /*---------------------------------------------------------------------*/
2454 /* the following routines dumps type information without any ir nodes. */
2455 /*---------------------------------------------------------------------*/
2458 dump_type_graph (ir_graph *irg, const char *suffix)
2462 rem = current_ir_graph;
2464 /* if a filter is set, dump only the irg's that match the filter */
2465 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2467 current_ir_graph = irg;
2469 f = vcg_open(irg, suffix, "-type");
2470 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2472 /* walk over the blocks in the graph */
2473 type_walk_irg(irg, dump_type_info, NULL, f);
2474 /* The walker for the const code can be called several times for the
2475 same (sub) expression. So that no nodes are dumped several times
2476 we decrease the visited flag of the corresponding graph after each
2477 walk. So now increase it finally. */
2478 inc_irg_visited(get_const_code_irg());
2481 current_ir_graph = rem;
2485 dump_all_types (const char *suffix)
2487 FILE *f = vcg_open_name("All_types", suffix);
2488 dump_vcg_header(f, "All_types", NULL);
2489 type_walk(dump_type_info, NULL, f);
2490 inc_irg_visited(get_const_code_irg());
2495 dump_class_hierarchy (bool entities, const char *suffix)
2497 FILE *f = vcg_open_name("class_hierarchy", suffix);
2501 dump_vcg_header(f, "class_hierarchy", NULL);
2506 type_walk(dump_class_hierarchy_node, NULL, &env);
2510 /*---------------------------------------------------------------------*/
2511 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2513 /* dump_ir_block_graph */
2515 /* dump_type_graph */
2516 /* dump_ir_graph_w_types */
2517 /*---------------------------------------------------------------------*/
2519 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2520 int i, n_irgs = get_irp_n_irgs();
2521 for (i = 0; i < n_irgs; ++i) {
2522 dmp_grph(get_irp_irg(i), suffix);
2527 /*--------------------------------------------------------------------------------*
2528 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2529 * packed together in one subgraph/box *
2530 *--------------------------------------------------------------------------------*/
2532 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2533 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2535 ir_loop *son = NULL;
2537 /* Dump a new loop node. */
2538 dump_loop_node(F, loop);
2540 /* Dump the loop elements. */
2542 for(i = 0; i < get_loop_n_elements(loop); i++) {
2543 le = get_loop_element(loop, i);
2545 if (get_kind(son) == k_ir_loop) {
2547 /* We are a loop son -> Recurse */
2549 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2550 fprintf(F, "\" }\n");
2551 fprintf (F, "edge: {sourcename: \"");
2553 fprintf (F, "\" targetname: \"");
2555 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2556 loop_node_started = 0;
2558 dump_loop_son_edge(F, loop, son_number++);
2559 dump_loops_standalone(F, son);
2560 } else if (get_kind(son) == k_ir_node) {
2561 /* We are a loop node -> Collect firm nodes */
2563 ir_node *n = le.node;
2566 if (!loop_node_started) {
2567 /* Start a new node which contains all firm nodes of the current loop */
2568 fprintf (F, "node: { title: \"");
2570 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2571 loop_node_started = 1;
2577 bad |= dump_node_label(F, n);
2578 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2579 if (has_backedges(n)) fprintf(F, "\t loop head!");
2580 } else { /* for callgraph loop tree */
2582 assert(get_kind(son) == k_ir_graph);
2584 /* We are a loop node -> Collect firm graphs */
2585 n = (ir_graph *)le.node;
2586 if (!loop_node_started) {
2587 /* Start a new node which contains all firm nodes of the current loop */
2588 fprintf (F, "node: { title: \"");
2590 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2591 loop_node_started = 1;
2596 fprintf (F, " %s", get_irg_dump_name(n));
2597 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2601 if (loop_node_started) {
2602 fprintf(F, "\" }\n");
2603 fprintf (F, "edge: {sourcename: \"");
2605 fprintf (F, "\" targetname: \"");
2607 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2608 loop_node_started = 0;
2612 void dump_loop_tree(ir_graph *irg, const char *suffix)
2615 ir_graph *rem = current_ir_graph;
2616 int el_rem = edge_label;
2619 /* if a filter is set, dump only the irg's that match the filter */
2620 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2622 current_ir_graph = irg;
2624 f = vcg_open(irg, suffix, "-looptree");
2625 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2627 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2631 edge_label = el_rem;
2632 current_ir_graph = rem;
2635 void dump_callgraph_loop_tree(const char *suffix) {
2637 F = vcg_open_name("Callgraph_looptree", suffix);
2638 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2639 dump_loops_standalone(F, irp->outermost_cg_loop);
2644 /*-----------------------------------------------------------------------------*/
2645 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2646 /*-----------------------------------------------------------------------------*/
2648 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2649 int i, son_number = 0, node_number = 0;
2651 if (dump_loop_information_flag) dump_loop_node(F, loop);
2653 for (i = 0; i < get_loop_n_elements(loop); i++) {
2654 loop_element le = get_loop_element(loop, i);
2655 if (*(le.kind) == k_ir_loop) {
2656 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2658 collect_nodeloop(F, le.son, loopnodes);
2660 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2661 eset_insert(loopnodes, le.node);
2666 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2669 for(i = 0; i < get_loop_n_elements(loop); i++) {
2670 loop_element le = get_loop_element(loop, i);
2671 if (*(le.kind) == k_ir_loop) {
2673 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2675 if (is_Block(le.node)) start = 0; else start = -1;
2676 for (j = start; j < get_irn_arity(le.node); j++) {
2677 ir_node *pred = get_irn_n(le.node, j);
2678 if (!eset_contains(loopnodes, pred)) {
2679 eset_insert(extnodes, pred);
2680 if (!is_Block(pred)) {
2681 pred = get_nodes_block(pred);
2682 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2690 void dump_loop(ir_loop *l, const char *suffix) {
2693 eset *loopnodes = eset_create();
2694 eset *extnodes = eset_create();
2697 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2698 F = vcg_open_name (name, suffix);
2699 dump_vcg_header(F, name, NULL);
2701 /* collect all nodes to dump */
2702 collect_nodeloop(F, l, loopnodes);
2703 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2705 /* build block lists */
2706 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2707 set_irn_link(n, NULL);
2708 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2709 set_irn_link(n, NULL);
2710 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2712 b = get_nodes_block(n);
2713 set_irn_link(n, get_irn_link(b));
2716 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2718 b = get_nodes_block(n);
2719 set_irn_link(n, get_irn_link(b));
2723 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2725 fprintf(F, "graph: { title: \"");
2727 fprintf(F, "\" label: \"");
2728 dump_node_opcode(F, b);
2729 fprintf (F, " %ld", get_irn_node_nr(b));
2730 fprintf(F, "\" status:clustered color:yellow\n");
2732 /* dump the blocks edges */
2733 dump_ir_data_edges(F, b);
2735 /* dump the nodes that go into the block */
2736 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2737 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2739 overrule_nodecolor = NULL;
2740 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2743 /* Close the vcg information for the block */
2745 dump_const_node_local(F, b);
2748 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2750 fprintf(F, "graph: { title: \"");
2752 fprintf(F, "\" label: \"");
2753 dump_node_opcode(F, b);
2754 fprintf (F, " %ld", get_irn_node_nr(b));
2755 fprintf(F, "\" status:clustered color:lightblue\n");
2757 /* dump the nodes that go into the block */
2758 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2759 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2761 overrule_nodecolor = NULL;
2762 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2765 /* Close the vcg information for the block */
2767 dump_const_node_local(F, b);
2771 eset_destroy(loopnodes);
2772 eset_destroy(extnodes);