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"
53 extern void dump_irn_chi_term(FILE *FL, ir_node *n);
54 extern void dump_irn_state(FILE *FL, ir_node *n);
55 extern int get_opt_dump_abstvals(void);
56 typedef unsigned long SeqNo;
57 extern SeqNo get_Block_seqno(ir_node *n);
60 /* basis for a color range for vcg */
61 static int n_colors = 0;
62 static int base_color = 0;
64 /** Dump only irgs with names that start with this string */
65 static ident *dump_file_filter_id = NULL;
67 #define ERROR_TXT "<ERROR>"
70 * returns the name of a mode or <ERROR> if mode is NOT a mode object.
71 * in the later case, sets bad
73 const char *get_mode_name_ex(ir_mode *mode, int *bad)
76 return get_mode_name(mode);
82 * returns the name of a type or <ERROR> if mode is NOT a mode object.
83 * in the later case, sets bad
85 const char *get_type_name_ex(type *tp, int *bad)
88 return get_type_name(tp);
94 * prints the edge from a type S to a type T with additional info fmt, ...
97 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
102 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
103 fprintf(F, " targetname: "); PRINT_TYPEID(T);
104 vfprintf(F, fmt, ap);
110 * prints the edge from a type T to an entity E with additional info fmt, ...
113 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
118 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
119 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
120 vfprintf(F, fmt, ap);
126 * prints the edge from an entity E to an entity T with additional info fmt, ...
129 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
135 fprintf(F, "backedge: { sourcename: \"");
137 fprintf(F, "edge: { sourcename: \"");
139 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
140 vfprintf(F, fmt, ap);
146 * prints the edge from an entity E to a type T with additional info fmt, ...
149 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
154 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
155 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
156 vfprintf(F, fmt, ap);
162 * prints the edge from a node N to a type T with additional info fmt, ...
165 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
170 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
171 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
172 vfprintf(F, fmt, ap);
178 * prints the edge from a node N to an entity E with additional info fmt, ...
181 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
186 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
187 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
189 vfprintf(F, fmt, ap);
195 * prints the edge from an entity E to a node N with additional info fmt, ...
198 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
203 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
204 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
205 vfprintf(F, fmt, ap);
211 * prints the edge from a type E to an enumeration item item with additional info fmt, ...
214 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
219 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
220 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
221 vfprintf(F, fmt, ap);
226 /*-----------------------------------------------------------------*/
227 /* global and ahead declarations */
228 /*-----------------------------------------------------------------*/
230 static void dump_whole_node(ir_node *n, void *env);
231 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
233 /*-----------------------------------------------------------------*/
234 /* Helper functions. */
235 /*-----------------------------------------------------------------*/
238 * This map is used as a private link attr to be able to call dumper
239 * anywhere without destroying link fields.
241 static pmap *irdump_link_map = NULL;
243 /** Creates the link attribut map. */
244 static void init_irdump(void) {
245 /* We need a new, empty map. */
246 if (irdump_link_map) pmap_destroy(irdump_link_map);
247 irdump_link_map = pmap_create();
248 dump_file_filter_id = new_id_from_str("");
251 * Returns the private link field.
253 static void *ird_get_irn_link(ir_node *n) {
255 if (!irdump_link_map) return NULL;
257 if (pmap_contains(irdump_link_map, (void *)n))
258 res = pmap_get(irdump_link_map, (void *)n);
263 * Sets the private link field.
265 static void ird_set_irn_link(ir_node *n, void *x) {
266 if (!irdump_link_map) init_irdump();
267 pmap_insert(irdump_link_map, (void *)n, x);
271 * Gets the private link field of an irg.
273 static void *ird_get_irg_link(ir_graph *irg) {
275 if (!irdump_link_map) return NULL;
277 if (pmap_contains(irdump_link_map, (void *)irg))
278 res = pmap_get(irdump_link_map, (void *)irg);
283 * Sets the private link field of an irg.
285 static void ird_set_irg_link(ir_graph *irg, void *x) {
286 if (!irdump_link_map) init_irdump();
287 pmap_insert(irdump_link_map, (void *)irg, x);
291 * Walker, clears the private link field.
293 static void clear_link(ir_node * node, void * env) {
294 ird_set_irn_link(node, NULL);
298 * If the entity has a ld_name, returns it, else returns the name of the entity.
300 const char *get_ent_dump_name(entity *ent) {
302 return "<NULL entity>";
303 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
304 if (ent->ld_name) return get_id_str(ent->ld_name);
305 return get_id_str(ent->name);
308 /* Returns the name of an IRG. */
309 const char *get_irg_dump_name(ir_graph *irg) {
310 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
311 entity *ent = get_irg_entity(irg);
312 return get_ent_dump_name(ent);
316 * Returns non-zero if a node is in floating state.
318 static int node_floats(ir_node *n) {
319 return ((get_irn_pinned(n) == op_pin_state_floats) &&
320 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
324 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
326 static void collect_node(ir_node * node, void *env) {
329 || get_irn_op(node) == op_Bad
330 || get_irn_op(node) == op_Unknown
331 || get_irn_op(node) == op_NoMem) {
332 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
333 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
334 ARR_APP1(ir_node *, arr, node);
335 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
337 ir_node * block = get_nodes_block(node);
340 /* this node is in a Bad block, so we must place it into the graph's list */
341 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
342 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
343 ARR_APP1(ir_node *, arr, node);
344 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
347 ird_set_irn_link(node, ird_get_irn_link(block));
348 ird_set_irn_link(block, node);
353 /** Construct lists to walk ir block-wise.
355 * Collects all blocks, nodes not op_pin_state_pinned,
356 * Bad, NoMem and Unknown into a flexible array in link field of
357 * irg they belong to. Sets the irg link field to NULL in all
358 * graphs not visited.
359 * Free the list with DEL_ARR_F().
361 static ir_node **construct_block_lists(ir_graph *irg) {
362 int i, rem_view = get_interprocedural_view();
363 ir_graph *rem = current_ir_graph;
364 current_ir_graph = irg;
366 for (i = 0; i < get_irp_n_irgs(); i++)
367 ird_set_irg_link(get_irp_irg(i), NULL);
369 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
371 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
372 set_interprocedural_view(false);
374 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
375 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
376 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
377 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
379 set_interprocedural_view(rem_view);
381 current_ir_graph = rem;
382 return ird_get_irg_link(irg);
385 typedef struct _list_tuple {
387 ir_extblk **extbb_list;
390 /** Construct lists to walk ir extended block-wise.
391 * Free the lists in the tuple with DEL_ARR_F().
393 static list_tuple *construct_extblock_lists(ir_graph *irg) {
394 ir_node **blk_list = construct_block_lists(irg);
396 ir_graph *rem = current_ir_graph;
397 list_tuple *lists = xmalloc(sizeof(*lists));
399 current_ir_graph = irg;
401 lists->blk_list = NEW_ARR_F(ir_node *, 0);
402 lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
404 for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
407 if (is_Block(blk_list[i])) {
408 ext = get_Block_extbb(blk_list[i]);
410 if (extbb_not_visited(ext)) {
411 ARR_APP1(ir_extblk *, lists->extbb_list, ext);
412 mark_extbb_visited(ext);
416 ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
419 current_ir_graph = rem;
421 ird_set_irg_link(irg, lists);
425 /*******************************************************************/
426 /* flags to steer output */
427 /*******************************************************************/
429 /** A compiler option to turn off edge labels */
430 static int edge_label = 1;
431 /** A compiler option to turn off dumping values of constant entities */
432 static int const_entities = 1;
433 /** A compiler option to dump the keep alive edges */
434 static int dump_keepalive = 0;
435 /** Compiler options to dump analysis information in dump_ir_graph */
436 int dump_out_edge_flag = 0;
437 int dump_dominator_information_flag = 0;
438 int dump_loop_information_flag = 0;
439 int dump_backedge_information_flag = 1;
440 int dump_const_local = 0;
441 bool opt_dump_analysed_type_info = 1;
442 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
444 static const char *overrule_nodecolor = NULL;
446 /** The vcg attribute hook. */
447 static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
450 void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
451 dump_node_vcgattr_hook = hook;
454 INLINE bool get_opt_dump_const_local(void) {
455 if (!dump_out_edge_flag && !dump_loop_information_flag)
456 return dump_const_local;
461 void only_dump_method_with_name(ident *name) {
462 dump_file_filter_id = name;
465 ident *get_dump_file_filter_ident(void) {
466 return dump_file_filter_id;
469 /** Returns true if dump file filter is not set, or if it is a
471 int is_filtered_dump_name(ident *name) {
472 if (!dump_file_filter_id) return 1;
473 return id_is_prefix(dump_file_filter_id, name);
476 /* To turn off display of edge labels. Edge labels offen cause xvcg to
477 abort with a segmentation fault. */
478 void turn_off_edge_labels(void) {
482 void dump_consts_local(bool b) {
483 dump_const_local = b;
486 void dump_constant_entity_values(bool b) {
490 void dump_keepalive_edges(bool b) {
494 bool get_opt_dump_keepalive_edges(void) {
495 return dump_keepalive;
498 void dump_out_edges(bool b) {
499 dump_out_edge_flag = b;
502 void dump_dominator_information(bool b) {
503 dump_dominator_information_flag = b;
506 void dump_loop_information(bool b) {
507 dump_loop_information_flag = b;
510 void dump_backedge_information(bool b) {
511 dump_backedge_information_flag = b;
514 /* Dump the information of type field specified in ana/irtypeinfo.h.
515 * If the flag is set, the type name is output in [] in the node label,
516 * else it is output as info.
518 void set_opt_dump_analysed_type_info(bool b) {
519 opt_dump_analysed_type_info = b;
522 void dump_pointer_values_to_info(bool b) {
523 opt_dump_pointer_values_to_info = b;
526 /*-----------------------------------------------------------------*/
527 /* Routines to dump information about a single ir node. */
528 /*-----------------------------------------------------------------*/
531 * dump the name of a node n to the File F.
534 dump_node_opcode(FILE *F, ir_node *n)
538 switch(get_irn_opcode(n)) {
543 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
544 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
549 if (get_SymConst_kind(n) == symconst_addr_name) {
550 /* don't use get_SymConst_ptr_info as it mangles the name. */
551 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
552 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
553 assert(get_SymConst_entity(n));
554 assert(is_entity(get_SymConst_entity(n)));
555 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
557 assert(get_kind(get_SymConst_type(n)) == k_type);
558 assert(get_type_ident(get_SymConst_type(n)));
559 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
560 if (get_SymConst_kind(n) == symconst_type_tag)
568 if (!get_interprocedural_view())
575 ir_node *pred = get_Proj_pred(n);
577 if (get_irn_opcode(pred) == iro_Cond
578 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
579 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
580 fprintf (F, "defProj");
582 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
583 * fprintf (F, "Arg");
592 if (get_interprocedural_view()) {
593 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
598 case iro_CallBegin: {
599 ir_node *addr = get_CallBegin_ptr(n);
601 if (get_irn_op(addr) == op_Sel)
602 ent = get_Sel_entity(addr);
603 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
604 ent = get_SymConst_entity(addr);
605 fprintf (F, "%s", get_irn_opname(n));
606 if (ent) fprintf (F, " %s", get_entity_name(ent));
610 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
615 fprintf (F, "%s", get_irn_opname(n));
623 * Dump the mode of a node n to a file F.
624 * Ignore modes that are "always known".
627 dump_node_mode(FILE *F, ir_node *n)
630 opcode iro = get_irn_opcode(n);
643 ir_mode *mode = get_irn_mode(n);
645 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
646 (mode != mode_T || iro == iro_Proj))
647 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
655 * Dump the type of a node n to a file F if it's known.
657 static int dump_node_typeinfo(FILE *F, ir_node *n) {
660 if (opt_dump_analysed_type_info) {
661 if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent ||
662 get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
663 type *tp = get_irn_typeinfo_type(n);
664 if (tp != firm_none_type)
665 fprintf(F, "[%s] ", get_type_name_ex(tp, &bad));
674 * Dump additional node attributes of some nodes to a file F.
677 dump_node_nodeattr(FILE *F, ir_node *n)
681 switch (get_irn_opcode(n)) {
683 if (false && get_interprocedural_view()) {
684 fprintf (F, "%s ", get_ent_dump_name(get_irg_entity(current_ir_graph)));
688 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
689 fprintf (F, "%s ", get_pnc_string(get_Proj_proj(n)));
691 fprintf (F, "%ld ", get_Proj_proj(n));
695 fprintf (F, "%ld ", get_Filter_proj(n));
698 fprintf (F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
701 fprintf (F, "(%s) ", get_type_name_ex(get_Cast_type(n), &bad));
704 fprintf (F, "%s ", get_pnc_string(get_Confirm_cmp(n)));
715 #include "execution_frequency.h"
716 #include "callgraph.h"
718 void dump_node_ana_vals(FILE *F, ir_node *n) {
720 fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
721 get_irn_exec_freq(n),
722 get_irg_method_execution_frequency(get_irn_irg(n)),
723 pow(5, get_irg_recursion_depth(get_irn_irg(n))),
724 get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
729 /* Dumps a node label without the enclosing ". */
730 int dump_node_label(FILE *F, ir_node *n) {
733 bad |= dump_node_opcode(F, n);
734 bad |= dump_node_mode(F, n);
736 bad |= dump_node_typeinfo(F, n);
737 bad |= dump_node_nodeattr(F, n);
738 fprintf(F, "%ld", get_irn_node_nr(n));
745 * Dumps the attributes of a node n into the file F.
746 * Currently this is only the color of a node.
748 static void dump_node_vcgattr(FILE *F, ir_node *node, ir_node *local, int bad)
753 fprintf(F, "color: red");
757 if (dump_node_vcgattr_hook)
758 if (dump_node_vcgattr_hook(F, node, local))
761 n = local ? local : node;
763 switch (get_irn_opcode(n)) {
770 fprintf (F, "color: blue");
773 if (is_Block_dead(n))
774 fprintf (F, "color: lightred");
776 fprintf (F, "color: lightyellow");
779 fprintf (F, "color: green");
785 fprintf (F, "color: yellow");
788 PRINT_DEFAULT_NODE_ATTR;
791 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
796 * Dump the node information of a node n to a file F.
798 static INLINE int dump_node_info(FILE *F, ir_node *n)
800 fprintf (F, " info1: \"");
801 bad = dump_irnode_to_file(F, n);
807 * checks whether a node is "constant-like" ie can be treated "block-less"
810 bool is_constlike_node(ir_node *n) {
811 ir_op *op = get_irn_op(n);
812 return (op == op_Const || op == op_Bad || op == op_NoMem || op == op_SymConst || op == op_Unknown);
816 /** outputs the predecessors of n, that are constants, local. I.e.,
817 generates a copy of the constant predecessors for each node called with. */
818 static void dump_const_node_local(FILE *F, ir_node *n) {
820 if (!get_opt_dump_const_local()) return;
822 /* Use visited flag to avoid outputting nodes twice.
823 initialize it first. */
824 for (i = 0; i < get_irn_arity(n); i++) {
825 ir_node *con = get_irn_n(n, i);
826 if (is_constlike_node(con)) {
827 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
831 for (i = 0; i < get_irn_arity(n); i++) {
832 ir_node *con = get_irn_n(n, i);
833 if (is_constlike_node(con) && irn_not_visited(con)) {
836 mark_irn_visited(con);
837 /* Generate a new name for the node by appending the names of
839 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
840 fprintf(F, " label: \"");
841 bad |= dump_node_label(F, con);
843 bad |= dump_node_info(F, con);
844 dump_node_vcgattr(F, n, con, bad);
850 /** If the block of an edge is a const_like node, dump it local with an edge */
851 static void dump_const_block_local(FILE *F, ir_node *n) {
854 if (!get_opt_dump_const_local()) return;
856 blk = get_nodes_block(n);
857 if (is_constlike_node(blk)) {
860 /* Generate a new name for the node by appending the names of
862 fprintf(F, "node: {title: \""); PRINT_CONSTBLKID(n, blk);
863 fprintf(F, "\" label: \"");
864 bad |= dump_node_label(F, blk);
866 bad |= dump_node_info(F, blk);
867 dump_node_vcgattr(F, n, blk, bad);
870 fprintf (F, "edge: { sourcename: \"");
872 fprintf (F, "\" targetname: \""); PRINT_CONSTBLKID(n,blk);
873 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
878 * prints the error message of a node to a file F as info2.
880 static void INLINE print_node_error(FILE *F, const char *err_msg)
885 fprintf (F, " info2: \"%s\"", err_msg);
891 static void dump_node(FILE *F, ir_node *n)
896 if (get_opt_dump_const_local() && is_constlike_node(n))
900 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
902 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
903 bad |= dump_node_label(F, n);
904 dump_node_ana_vals(F, n);
905 //dump_node_ana_info(F, n);
907 bad |= dump_node_info(F, n);
908 print_node_error(F, p);
909 dump_node_vcgattr(F, n, NULL, bad);
911 dump_const_node_local(F, n);
913 dump_irn_chi_term(F, n);
914 dump_irn_state(F, n);
918 /** dump the edge to the block this node belongs to */
920 dump_ir_block_edge(FILE *F, ir_node *n) {
921 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
922 if (is_no_Block(n)) {
923 ir_node *block = get_nodes_block(n);
925 if (get_opt_dump_const_local() && is_constlike_node(block)) {
926 dump_const_block_local(F, n);
929 fprintf (F, "edge: { sourcename: \"");
931 fprintf (F, "\" targetname: ");
932 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
933 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
939 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
940 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
941 fprintf (F, INTRA_DATA_EDGE_ATTR);
943 fprintf (F, INTER_DATA_EDGE_ATTR);
947 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
948 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
949 fprintf (F, INTRA_MEM_EDGE_ATTR);
951 fprintf (F, INTER_MEM_EDGE_ATTR);
955 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
958 if (dump_backedge_information_flag && is_backedge(from, to))
959 fprintf (F, BACK_EDGE_ATTR);
961 switch (get_irn_opcode(from)) {
963 fprintf (F, CF_EDGE_ATTR);
965 case iro_Start: break;
968 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
969 fprintf (F, CF_EDGE_ATTR);
970 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
971 fprintf (F, INTER_MEM_EDGE_ATTR);
979 print_data_edge_vcgattr(F, from, to);
984 print_mem_edge_vcgattr(F, from, to);
986 print_data_edge_vcgattr(F, from, to);
990 print_data_edge_vcgattr(F, from, to);
995 print_mem_edge_vcgattr(F, from, to);
997 print_data_edge_vcgattr(F, from, to);
1004 print_data_edge_vcgattr(F, from, to);
1011 print_mem_edge_vcgattr(F, from, to);
1013 print_data_edge_vcgattr(F, from, to);
1025 print_data_edge_vcgattr(F, from, to);
1028 if (get_irn_modecode(from) == irm_M)
1029 fprintf (F, INTER_MEM_EDGE_ATTR);
1031 print_data_edge_vcgattr(F, from, to);
1038 print_mem_edge_vcgattr(F, from, to);
1040 print_data_edge_vcgattr(F, from, to);
1043 print_mem_edge_vcgattr(F, from, to);
1045 case iro_Tuple: break;
1048 switch (get_irn_modecode(from)) {
1050 fprintf (F, CF_EDGE_ATTR);
1053 fprintf (F, INTER_MEM_EDGE_ATTR);
1056 print_data_edge_vcgattr(F, from, to);
1060 case iro_Bad: break;
1061 case iro_Unknown: break;
1063 switch (get_irn_modecode(from)) {
1065 fprintf (F, INTRA_MEM_EDGE_ATTR);
1068 fprintf (F, CF_EDGE_ATTR);
1071 print_data_edge_vcgattr(F, from, to);
1079 /* dump edges to our inputs */
1081 dump_ir_data_edges(FILE *F, ir_node *n) {
1083 unsigned long visited = get_irn_visited(n);
1085 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1088 for (i = 0; i < get_irn_arity(n); i++) {
1089 ir_node * pred = get_irn_n(n, i);
1092 if ((get_interprocedural_view() && get_irn_visited(pred) < visited))
1093 continue; /* pred not dumped */
1095 if (dump_backedge_information_flag && is_backedge(n, i))
1096 fprintf (F, "backedge: {sourcename: \"");
1098 fprintf (F, "edge: {sourcename: \"");
1100 fprintf (F, "\" targetname: ");
1101 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1102 PRINT_CONSTID(n, pred);
1104 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1106 fprintf (F, " label: \"%d\" ", i);
1107 print_edge_vcgattr(F, n, i);
1112 /** Dumps a node and its edges but not the block edge
1115 dump_node_wo_blockedge (ir_node *n, void *env) {
1118 dump_ir_data_edges(F, n);
1121 /** Dumps a node and its edges.
1124 dump_whole_node (ir_node *n, void *env) {
1126 dump_node_wo_blockedge(n, env);
1127 if (!node_floats(n)) dump_ir_block_edge(F, n);
1131 dump_const_node(ir_node *n, void *env) {
1132 if (is_Block(n)) return;
1133 dump_node_wo_blockedge(n, env);
1136 /***********************************************************************/
1137 /* the following routines dump the nodes/irgs bracketed to graphs. */
1138 /***********************************************************************/
1140 /** Dumps a constant expression as entity initializer, array bound ...
1142 static void dump_const_expression(FILE *F, ir_node *value) {
1143 ir_graph *rem = current_ir_graph;
1144 int rem_dump_const_local = dump_const_local;
1145 dump_const_local = 0;
1146 current_ir_graph = get_const_code_irg();
1147 irg_walk(value, dump_const_node, NULL, F);
1148 /* Decrease visited flag so that we walk with the same flag for the next
1149 expression. This guarantees that we don't dump the same node twice,
1150 as for const expressions cse is performed to save memory. */
1151 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1152 current_ir_graph = rem;
1153 dump_const_local = rem_dump_const_local;
1156 /** Dump a block as graph containing its nodes.
1158 * Expects to find nodes belonging to the block as list in its
1160 * Dumps the edges of all nodes including itself. */
1162 dump_whole_block(FILE *F, ir_node *block) {
1164 assert(is_Block(block));
1166 fprintf(F, "graph: { title: \"");
1167 PRINT_NODEID(block);
1168 fprintf(F, "\" label: \"");
1169 dump_node_label(F, block);
1171 if (get_opt_dump_abstvals())
1172 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1174 fprintf(F, "\" status:clustered color:%s \n",
1175 get_Block_matured(block) ? "yellow" : "red");
1177 /* dump the blocks edges */
1178 dump_ir_data_edges(F, block);
1180 /* dump the nodes that go into the block */
1181 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1183 dump_ir_data_edges(F, node);
1186 /* Close the vcg information for the block */
1188 dump_const_node_local(F, block);
1190 dump_irn_chi_term(F, block);
1195 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1196 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1198 dump_block_graph(FILE *F, ir_graph *irg) {
1200 ir_graph *rem = current_ir_graph;
1201 ir_node **arr = ird_get_irg_link(irg);
1202 current_ir_graph = irg;
1204 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1205 ir_node * node = arr[i];
1206 if (is_Block(node)) {
1207 /* Dumps the block and all the nodes in the block, which are to
1208 be found in Block->link. */
1209 dump_whole_block(F, node);
1211 /* Nodes that are not in a Block. */
1213 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1214 dump_const_block_local(F, node);
1216 dump_ir_data_edges(F, node);
1220 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1221 dump_loop_nodes_into_graph(F, irg);
1223 current_ir_graph = rem;
1226 /** Dumps an irg as a graph clustered by block nodes.
1227 * If interprocedural view edges can point to nodes out of this graph.
1229 static void dump_graph_from_list(FILE *F, ir_graph *irg) {
1231 fprintf(F, "graph: { title: \"");
1233 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1234 get_ent_dump_name(get_irg_entity(irg)));
1236 dump_block_graph(F, irg);
1238 /* Close the vcg information for the irg */
1239 fprintf(F, "}\n\n");
1242 /** dumps a graph extended block-wise. Expects all blockless nodes in arr in irgs link.
1243 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1245 dump_extblock_graph(FILE *F, ir_graph *irg) {
1247 ir_graph *rem = current_ir_graph;
1248 ir_extblk **arr = ird_get_irg_link(irg);
1249 current_ir_graph = irg;
1252 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1253 ir_extblk *extbb = arr[i];
1254 ir_node *leader = extbb->blks[0];
1257 fprintf(F, "graph: { title: \"");
1258 PRINT_EXTBBID(leader);
1259 fprintf(F, "\" label: \"ExtBB %ld\" status:clustered color:lightgreen\n",
1260 get_irn_node_nr(leader));
1262 for (j = ARR_LEN(extbb->blks) - 1; j >= 0; --j) {
1263 ir_node * node = extbb->blks[j];
1264 if (is_Block(node)) {
1265 /* Dumps the block and all the nodes in the block, which are to
1266 be found in Block->link. */
1267 dump_whole_block(F, node);
1269 /* Nodes that are not in a Block. */
1271 if (is_Bad(get_nodes_block(node)) && !node_floats(node)) {
1272 dump_const_block_local(F, node);
1274 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;
1288 /*******************************************************************/
1289 /* Basic type and entity nodes and edges. */
1290 /*******************************************************************/
1292 /** dumps the edges between nodes and their type or entity attributes. */
1293 static void dump_node2type_edges(ir_node *n, void *env)
1298 switch (get_irn_opcode(n)) {
1300 /* @@@ some consts have an entity */
1303 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1304 || (get_SymConst_kind(n) ==symconst_size))
1306 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1310 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1313 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1316 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1319 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1322 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1330 static int print_type_info(FILE *F, type *tp) {
1333 if (get_type_state(tp) == layout_undefined) {
1334 fprintf(F, "state: layout_undefined\n");
1336 fprintf(F, "state: layout_fixed,\n");
1338 if (get_type_mode(tp))
1339 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1340 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1345 static void print_typespecific_info(FILE *F, type *tp) {
1346 switch (get_type_tpop_code(tp)) {
1349 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1356 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1357 fprintf(F, "params: %d\n", get_method_n_params(tp));
1358 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1366 case tpo_enumeration:
1380 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1381 switch (get_type_tpop_code(tp)) {
1384 if (peculiarity_existent == get_class_peculiarity(tp))
1385 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1387 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1391 fprintf (F, " " TYPE_METH_NODE_ATTR);
1402 case tpo_enumeration:
1416 /* Why not dump_type_node as the others? */
1417 static int print_type_node(FILE *F, type *tp)
1421 fprintf (F, "node: {title: ");
1423 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1424 fprintf (F, " info1: \"");
1426 bad |= print_type_info(F, tp);
1427 print_typespecific_info(F, tp);
1429 dump_type_to_file(F, tp, dump_verbosity_max);
1432 print_typespecific_vcgattr(F, tp);
1438 int dump_type_node(FILE *F, type *tp) {
1439 return print_type_node(F, tp);
1443 #define X(a) case a: fprintf(F, #a); break
1444 void dump_entity_node(FILE *F, entity *ent, int color)
1446 fprintf (F, "node: {title: \"");
1447 PRINT_ENTID(ent); fprintf(F, "\"");
1448 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1449 fprintf (F, "label: ");
1450 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1452 fprintf(F, "color: %d", color);
1454 fprintf (F, ENTITY_NODE_ATTR);
1455 fprintf (F, "\n info1: \"");
1457 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1459 fprintf(F, "\"\n}\n");
1463 static void dump_enum_item(FILE *F, type *tp, int pos)
1466 ident *id = get_enumeration_nameid(tp, pos);
1467 tarval *tv = get_enumeration_enum(tp, pos);
1469 tarval_snprintf(buf, sizeof(buf), tv);
1470 fprintf (F, "node: {title: \"");
1471 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1472 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1473 fprintf (F, "label: ");
1474 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1475 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1478 /* dumps a type or entity and it's edges. */
1480 dump_type_info(type_or_ent *tore, void *env) {
1482 int i = 0; /* to shutup gcc */
1484 /* dump this type or entity */
1486 switch (get_kind(tore)) {
1489 entity *ent = (entity *)tore;
1492 dump_entity_node(F, ent, 0);
1494 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1495 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1496 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1497 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1498 if (is_Class_type(get_entity_owner(ent))) {
1499 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1500 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1502 /* attached subgraphs */
1503 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1504 if (is_atomic_entity(ent)) {
1505 value = get_atomic_ent_value(ent);
1507 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1508 /* DDMN(value); $$$ */
1509 dump_const_expression(F, value);
1512 if (is_compound_entity(ent)) {
1513 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1514 value = get_compound_ent_value(ent, i);
1516 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1517 dump_const_expression(F, value);
1518 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1520 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1521 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1522 get_compound_ent_value_member(ent, i), i);
1531 type *tp = (type *)tore;
1532 print_type_node(F, tp);
1533 /* and now the edges */
1534 switch (get_type_tpop_code(tp)) {
1537 for (i=0; i < get_class_n_supertypes(tp); i++)
1538 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1539 for (i=0; i < get_class_n_members(tp); i++)
1540 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1544 for (i=0; i < get_struct_n_members(tp); i++)
1545 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1549 for (i = 0; i < get_method_n_params(tp); i++)
1550 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1551 for (i = 0; i < get_method_n_ress(tp); i++)
1552 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1556 for (i = 0; i < get_union_n_members(tp); i++)
1557 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1561 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1562 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1563 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1564 ir_node *upper = get_array_upper_bound(tp, i);
1565 ir_node *lower = get_array_lower_bound(tp, i);
1566 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1567 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1568 dump_const_expression(F, upper);
1569 dump_const_expression(F, lower);
1573 case tpo_enumeration:
1575 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1576 dump_enum_item(F, tp, i);
1577 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1582 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1590 break; /* case k_type */
1593 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1595 } /* switch kind_or_entity */
1598 typedef struct _h_env {
1603 /** For dumping class hierarchies.
1604 * Dumps a class type node and a superclass edge.
1605 * If env->dump_ent dumps entities of classes and overwrites edges.
1608 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1611 int i = 0; /* to shutup gcc */
1613 /* dump this type or entity */
1614 switch (get_kind(tore)) {
1616 entity *ent = (entity *)tore;
1617 if (get_entity_owner(ent) == get_glob_type()) break;
1618 if (!is_Method_type(get_entity_type(ent))) break; /* GL */
1619 if (env->dump_ent && is_Class_type(get_entity_owner(ent))) {
1621 dump_entity_node(F, ent, 0);
1623 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1624 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1625 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1627 } break; /* case k_entity */
1630 type *tp = (type *)tore;
1631 if (tp == get_glob_type()) break;
1632 switch (get_type_tpop_code(tp)) {
1634 print_type_node(F, tp);
1635 /* and now the edges */
1636 for (i=0; i < get_class_n_supertypes(tp); i++)
1638 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1644 break; /* case k_type */
1647 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1649 } /* switch kind_or_entity */
1652 /*******************************************************************/
1653 /* dump analysis information that is expressed in graph terms. */
1654 /*******************************************************************/
1656 /* dump out edges */
1658 dump_out_edge(ir_node *n, void *env) {
1661 for (i = 0; i < get_irn_n_outs(n); i++) {
1662 assert(get_irn_out(n, i));
1663 fprintf (F, "edge: {sourcename: \"");
1665 fprintf (F, "\" targetname: \"");
1666 PRINT_NODEID(get_irn_out(n, i));
1667 fprintf (F, "\" color: red linestyle: dashed");
1673 dump_loop_label(FILE *F, ir_loop *loop) {
1674 fprintf (F, "loop %d, %d sons, %d nodes",
1675 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1678 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1679 fprintf (F, " info1: \"");
1680 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1681 #if DEBUG_libfirm /* GL @@@ debug analyses */
1682 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1688 dump_loop_node(FILE *F, ir_loop *loop) {
1689 fprintf (F, "node: {title: \"");
1691 fprintf (F, "\" label: \"");
1692 dump_loop_label(F, loop);
1694 dump_loop_info(F, loop);
1700 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1702 fprintf (F, "edge: {sourcename: \"");
1704 fprintf (F, "\" targetname: \"");
1705 PRINT_NODEID(get_loop_node(loop, i));
1706 fprintf (F, "\" color: green");
1711 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1713 fprintf (F, "edge: {sourcename: \"");
1715 fprintf (F, "\" targetname: \"");
1716 PRINT_LOOPID(get_loop_son(loop, i));
1717 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1718 get_loop_element_pos(loop, get_loop_son(loop, i)));
1722 void dump_loops(FILE *F, ir_loop *loop) {
1724 /* dump this loop node */
1725 dump_loop_node(F, loop);
1727 /* dump edges to nodes in loop -- only if it is a real loop */
1728 if (get_loop_depth(loop) != 0) {
1729 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1730 dump_loop_node_edge(F, loop, i);
1733 for (i = 0; i < get_loop_n_sons(loop); i++) {
1734 dump_loops(F, get_loop_son(loop, i));
1735 dump_loop_son_edge(F, loop, i);
1740 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1741 ir_graph *rem = current_ir_graph;
1742 current_ir_graph = irg;
1744 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1746 current_ir_graph = rem;
1751 * dumps the VCG header
1753 INLINE void dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1762 if (!orientation) orientation = "bottom_to_top";
1766 "graph: { title: \"ir graph of %s\"\n"
1767 "display_edge_labels: %s\n"
1768 "layoutalgorithm: mindepth\n"
1769 "manhattan_edges: yes\n"
1770 "port_sharing: no\n"
1772 "classname 1: \"intrablock Data\"\n"
1773 "classname 16: \"interblock Data\"\n"
1774 "classname 2: \"Block\"\n"
1775 "classname 13: \"Control Flow\"\n"
1776 "classname 18: \"Exception Control Flow for Interval Analysis\"\n"
1777 "classname 14: \"intrablock Memory\"\n"
1778 "classname 17: \"interblock Memory\"\n"
1779 "classname 15: \"Dominators\"\n"
1780 "classname 3: \"Entity type\"\n"
1781 "classname 4: \"Entity owner\"\n"
1782 "classname 5: \"Method Param\"\n"
1783 "classname 6: \"Method Res\"\n"
1784 "classname 7: \"Super\"\n"
1785 "classname 8: \"Union\"\n"
1786 "classname 9: \"Points-to\"\n"
1787 "classname 10: \"Array Element Type\"\n"
1788 "classname 11: \"Overwrites\"\n"
1789 "classname 12: \"Member\"\n"
1790 "infoname 1: \"Attribute\"\n"
1791 "infoname 2: \"Verification errors\"\n",
1792 name, label, orientation);
1794 /* don't use all, the range is too whith/black. */
1798 "colorentry 100: 0 0 0\n"
1799 "colorentry 101: 20 0 0\n"
1800 "colorentry 102: 40 0 0\n"
1801 "colorentry 103: 60 0 0\n"
1802 "colorentry 104: 80 0 0\n"
1803 "colorentry 105: 100 0 0\n"
1804 "colorentry 106: 120 0 0\n"
1805 "colorentry 107: 140 0 0\n"
1806 "colorentry 108: 150 0 0\n"
1807 "colorentry 109: 180 0 0\n"
1808 "colorentry 110: 200 0 0\n"
1809 "colorentry 111: 220 0 0\n"
1810 "colorentry 112: 240 0 0\n"
1811 "colorentry 113: 255 0 0\n"
1812 "colorentry 113: 255 20 20\n"
1813 "colorentry 114: 255 40 40\n"
1814 "colorentry 115: 255 60 60\n"
1815 "colorentry 116: 255 80 80\n"
1816 "colorentry 117: 255 100 100\n"
1817 "colorentry 118: 255 120 120\n"
1818 "colorentry 119: 255 140 140\n"
1819 "colorentry 120: 255 150 150\n"
1820 "colorentry 121: 255 180 180\n"
1821 "colorentry 122: 255 200 200\n"
1822 "colorentry 123: 255 220 220\n"
1823 "colorentry 124: 255 240 240\n"
1824 "colorentry 125: 255 250 250\n"
1827 fprintf (F, "\n"); /* a separator */
1833 * @param irg The graph to be dumped
1834 * @param suffix1 first filename suffix
1835 * @param suffix2 second filename suffix
1837 FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1839 const char *nm = get_irg_dump_name(irg);
1840 int len = strlen(nm), i, j;
1841 char *fname; /* filename to put the vcg information in */
1843 if (!suffix1) suffix1 = "";
1844 if (!suffix2) suffix2 = "";
1846 /* open file for vcg graph */
1847 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1849 /* strncpy (fname, nm, len); */ /* copy the filename */
1851 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1853 fname[j] = '@'; j++; fname[j] = '1'; j++;
1854 } else if (nm[i] == '@') {
1855 fname[j] = '@'; j++; fname[j] = '2'; j++;
1857 fname[j] = nm[i]; j++;
1861 strcat (fname, suffix1); /* append file suffix */
1862 strcat (fname, suffix2); /* append file suffix */
1863 strcat (fname, ".vcg"); /* append the .vcg suffix */
1865 /* vcg really expect only a <CR> at end of line, so
1866 * the "b"inary mode is what you mean (and even needed for Win32)
1868 F = fopen (fname, "wb"); /* open file for writing */
1870 panic("cannot open %s for writing (%m)", fname); /* not reached */
1880 * @param irg The graph to be dumped
1881 * @param suffix filename suffix
1883 FILE *vcg_open_name (const char *name, const char *suffix) {
1885 char *fname; /* filename to put the vcg information in */
1886 int i, j, len = strlen(name);
1888 if (!suffix) suffix = "";
1890 /** open file for vcg graph */
1891 fname = malloc (len * 2 + 5 + strlen(suffix));
1892 /* strcpy (fname, name);*/ /* copy the filename */
1894 for (i = 0; i < len; ++i) { /* replace '/' in the name: escape by @. */
1895 if (name[i] == '/') {
1896 fname[j] = '@'; j++; fname[j] = '1'; j++;
1897 } else if (name[i] == '@') {
1898 fname[j] = '@'; j++; fname[j] = '2'; j++;
1900 fname[j] = name[i]; j++;
1904 strcat (fname, suffix);
1905 strcat (fname, ".vcg"); /* append the .vcg suffix */
1907 /* vcg really expect only a <CR> at end of line, so
1908 * the "b"inary mode is what you mean (and even needed for Win32)
1910 F = fopen (fname, "wb"); /* open file for writing */
1912 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1920 * Dumps the vcg file footer
1922 static INLINE void dump_vcg_footer (FILE *F) {
1927 * close the vcg file
1929 void vcg_close (FILE *F) {
1930 dump_vcg_footer(F); /* print footer */
1931 fclose (F); /* close vcg file */
1934 /************************************************************************/
1935 /************************************************************************/
1936 /* Routines that dump all or parts of the firm representation to a file */
1937 /************************************************************************/
1938 /************************************************************************/
1940 /************************************************************************/
1941 /* Dump ir graphs, different formats and additional information. */
1942 /************************************************************************/
1944 /** Routine to dump a graph, blocks as conventional nodes. */
1946 dump_ir_graph (ir_graph *irg, const char *suffix )
1951 rem = current_ir_graph;
1953 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
1955 current_ir_graph = irg;
1956 if (get_interprocedural_view()) suffix1 = "-pure-ip";
1957 else suffix1 = "-pure";
1958 f = vcg_open(irg, suffix, suffix1);
1959 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1961 /* walk over the graph */
1962 /* dump_whole_node must be called in post visiting predecessors */
1963 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1965 /* dump the out edges in a separate walk */
1966 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1967 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, f);
1972 current_ir_graph = rem;
1975 /* Dump a firm graph without explicit block nodes. */
1976 void dump_ir_block_graph (ir_graph *irg, const char *suffix)
1982 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
1985 if (get_interprocedural_view()) suffix1 = "-ip";
1987 f = vcg_open(irg, suffix, suffix1);
1988 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1990 construct_block_lists(irg);
1993 * If we are in the interprocedural view, we dump not
1994 * only the requested irg but also all irgs that can be reached
1997 for (i = 0; i < get_irp_n_irgs(); i++) {
1998 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2000 dump_graph_from_list(f, get_irp_irg(i));
2008 /* Dump a firm graph without explicit block nodes but grouped in extended blocks. */
2009 void dump_ir_extblock_graph (ir_graph *irg, const char *suffix)
2015 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2020 if (get_interprocedural_view()) suffix1 = "-ip";
2022 F = vcg_open(irg, suffix, suffix1);
2023 dump_vcg_header(F, get_irg_dump_name(irg), NULL);
2025 construct_extblock_lists(irg);
2027 fprintf(F, "graph: { title: \"");
2029 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
2030 get_ent_dump_name(get_irg_entity(irg)));
2032 for (i = 0; i < get_irp_n_irgs(); i++) {
2033 ir_graph *irg = get_irp_irg(i);
2034 list_tuple *lists = ird_get_irg_link(irg);
2037 /* dump the extended blocks first */
2038 if (ARR_LEN(lists->extbb_list)) {
2039 ird_set_irg_link(irg, lists->extbb_list);
2040 dump_extblock_graph(F, irg);
2043 /* we may have blocks without extended blocks, bad for instance */
2044 if (ARR_LEN(lists->blk_list)) {
2045 ird_set_irg_link(irg, lists->blk_list);
2046 dump_block_graph(F, irg);
2049 DEL_ARR_F(lists->extbb_list);
2050 DEL_ARR_F(lists->blk_list);
2055 /* Close the vcg information for the irg */
2056 fprintf(F, "}\n\n");
2062 /* dumps a graph with type information */
2064 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
2067 ir_graph *rem = current_ir_graph;
2070 /* if a filter is set, dump only the irg's that match the filter */
2071 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2074 current_ir_graph = irg;
2076 if (get_interprocedural_view()) suffix1 = "-pure-wtypes-ip";
2077 else suffix1 = "-pure-wtypes";
2078 f = vcg_open(irg,suffix, suffix1);
2079 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2081 /* dump common ir graph */
2082 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
2083 /* dump type info */
2084 type_walk_irg(irg, dump_type_info, NULL, f);
2085 inc_irg_visited(get_const_code_irg());
2086 /* dump edges from graph to type info */
2087 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2090 current_ir_graph = rem;
2094 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
2099 ir_graph *rem = current_ir_graph;
2101 /* if a filter is set, dump only the irg's that match the filter */
2102 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2105 if (get_interprocedural_view()) suffix1 = "-wtypes-ip";
2106 else suffix1 = "-wtypes";
2107 f = vcg_open(irg, suffix, suffix1);
2108 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2110 /* dump common blocked ir graph */
2111 construct_block_lists(irg);
2113 for (i = 0; i < get_irp_n_irgs(); i++) {
2114 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
2116 dump_graph_from_list(f, get_irp_irg(i));
2121 /* dump type info */
2122 current_ir_graph = irg;
2123 type_walk_irg(irg, dump_type_info, NULL, f);
2124 inc_irg_visited(get_const_code_irg());
2126 /* dump edges from graph to type info */
2127 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2129 current_ir_graph = rem;
2133 /*---------------------------------------------------------------------*/
2134 /* The following routines dump a control flow graph. */
2135 /*---------------------------------------------------------------------*/
2138 dump_block_to_cfg(ir_node *block, void *env) {
2143 if (is_Block(block)) {
2144 /* This is a block. Dump a node for the block. */
2145 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2146 fprintf (F, "\" label: \"");
2147 if (block == get_irg_start_block(get_irn_irg(block)))
2148 fprintf(F, "Start ");
2149 if (block == get_irg_end_block(get_irn_irg(block)))
2152 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2153 PRINT_NODEID(block);
2155 fprintf(F, "info1:\"");
2158 if (dump_dominator_information_flag) {
2159 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2160 fprintf(F, "tree pre num %d\n", get_Block_dom_tree_pre_num(block));
2161 fprintf(F, "max subtree pre num %d\n", get_Block_dom_max_subtree_pre_num(block));
2164 /* show arity and possible Bad predecessors of the block */
2165 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2166 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2167 ir_node *pred = get_Block_cfgpred(block, i);
2170 fprintf(F, "Bad pred at pos: ");
2171 fprintf(F, "%d ", i);
2178 /* the generic version. */
2179 dump_irnode_to_file(F, block);
2181 /* Check whether we have bad predecessors to color the block. */
2182 for (i = 0; i < get_Block_n_cfgpreds(block); ++i)
2183 if ((fl = is_Bad(get_Block_cfgpred(block, i))))
2187 fprintf (F, "\""); /* closing quote of info */
2189 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2190 (block == get_irg_end_block(get_irn_irg(block))) )
2191 fprintf(F, " color:blue ");
2193 fprintf(F, " color:yellow ");
2196 /* Dump the edges */
2197 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2198 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2199 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2200 fprintf (F, "edge: { sourcename: \"");
2201 PRINT_NODEID(block);
2202 fprintf (F, "\" targetname: \"");
2204 fprintf (F, "\"}\n");
2207 /* Dump dominator edge */
2208 if (dump_dominator_information_flag && get_Block_idom(block)) {
2209 pred = get_Block_idom(block);
2210 fprintf (F, "edge: { sourcename: \"");
2211 PRINT_NODEID(block);
2212 fprintf (F, "\" targetname: \"");
2214 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2220 dump_cfg (ir_graph *irg, const char *suffix)
2223 ir_graph *rem = current_ir_graph;
2224 int ddif = dump_dominator_information_flag;
2225 int ipv = get_interprocedural_view();
2227 /* if a filter is set, dump only the irg's that match the filter */
2228 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
2231 current_ir_graph = irg;
2233 f = vcg_open(irg, suffix, "-cfg");
2234 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2237 printf("Warning: dumping cfg not in interprocedural view!\n");
2238 set_interprocedural_view(false);
2241 if (get_irg_dom_state(irg) != dom_consistent)
2242 dump_dominator_information_flag = 0;
2244 /* walk over the blocks in the graph */
2245 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2246 dump_node(f, get_irg_bad(irg));
2248 dump_dominator_information_flag = ddif;
2249 set_interprocedural_view(ipv);
2251 current_ir_graph = rem;
2255 static void descend_and_dump(FILE *F, ir_node *n, int depth, pset *mark_set) {
2256 if (pset_find_ptr(mark_set, n)) return;
2258 pset_insert_ptr(mark_set, n);
2261 int i, start = is_Block(n) ? 0 : -1;
2262 dump_whole_node(n, F);
2263 for (i = start; i < get_irn_arity(n); ++i)
2264 descend_and_dump(F, get_irn_n(n, i), depth-1, mark_set);
2267 /* Don't dump edges to nodes further out. These might be edges to
2268 nodes we already dumped, if there is a shorter path to these. */
2272 static int subgraph_counter = 0;
2273 void dump_subgraph (ir_node *root, int depth, const char *suffix) {
2276 pset *mark_set = pset_new_ptr(1);
2277 sprintf(buf, "-subg_%03d", subgraph_counter++);
2278 F = vcg_open(get_irn_irg(root), suffix, buf);
2279 dump_vcg_header(F, get_irg_dump_name(get_irn_irg(root)), NULL);
2280 descend_and_dump(F, root, depth, mark_set);
2286 static int weight_overall(int rec, int loop) {
2287 return 2*rec + loop;
2290 static int compute_color (int my, int max) {
2297 /* if small, scale to the full color range. */
2299 my = my * (n_colors/max);
2301 step = 1 + (max / n_colors);
2305 return base_color + n_colors - color;
2308 static int get_entity_color(entity *ent) {
2309 ir_graph *irg = get_entity_irg(ent);
2313 int rec_depth = get_irg_recursion_depth(irg);
2314 int loop_depth = get_irg_loop_depth(irg);
2315 int overall_depth = weight_overall(rec_depth, loop_depth);
2317 int max_rec_depth = irp->max_callgraph_recursion_depth;
2318 int max_loop_depth = irp->max_callgraph_loop_depth;
2319 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2321 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2322 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2323 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2325 return my_overall_color;
2329 void dump_callgraph(const char *suffix) {
2331 int i, n_irgs = get_irp_n_irgs();
2332 int rem = edge_label;
2334 //ident *prefix = new_id_from_str("java/");
2336 F = vcg_open_name("Callgraph", suffix);
2337 dump_vcg_header(F, "Callgraph", NULL);
2339 for (i = 0; i < n_irgs; ++i) {
2340 ir_graph *irg = get_irp_irg(i);
2341 entity *ent = get_irg_entity(irg);
2342 int j, n_callees = get_irg_n_callees(irg);
2344 /* Do not dump runtime system. */
2345 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2347 dump_entity_node(F, ent, get_entity_color(ent));
2348 for (j = 0; j < n_callees; ++j) {
2349 entity *c = get_irg_entity(get_irg_callee(irg, j));
2350 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2351 int be = is_irg_callee_backedge(irg, j);
2354 "label:\"recursion %d\" color: %d" :
2355 "label:\"calls %d\" color: %d";
2356 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2364 /* Dump all irgs in interprocedural view to a single file. */
2365 void dump_all_cg_block_graph(const char *suffix) {
2368 int rem_view = get_interprocedural_view();
2369 set_interprocedural_view(true);
2371 f = vcg_open_name("All_graphs", suffix);
2372 dump_vcg_header(f, "All_graphs", NULL);
2374 /* collect nodes in all irgs reachable in call graph*/
2375 for (i = 0; i < get_irp_n_irgs(); i++)
2376 ird_set_irg_link(get_irp_irg(i), NULL);
2378 cg_walk(clear_link, collect_node, NULL);
2380 /* dump all graphs */
2381 for (i = 0; i < get_irp_n_irgs(); i++) {
2382 current_ir_graph = get_irp_irg(i);
2383 assert(ird_get_irg_link(current_ir_graph));
2384 dump_graph_from_list(f, current_ir_graph);
2385 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2389 set_interprocedural_view(rem_view);
2392 /*---------------------------------------------------------------------*/
2393 /* the following routines dumps type information without any ir nodes. */
2394 /*---------------------------------------------------------------------*/
2397 dump_type_graph (ir_graph *irg, const char *suffix)
2401 rem = current_ir_graph;
2403 /* if a filter is set, dump only the irg's that match the filter */
2404 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2406 current_ir_graph = irg;
2408 f = vcg_open(irg, suffix, "-type");
2409 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2411 /* walk over the blocks in the graph */
2412 type_walk_irg(irg, dump_type_info, NULL, f);
2413 /* The walker for the const code can be called several times for the
2414 same (sub) expression. So that no nodes are dumped several times
2415 we decrease the visited flag of the corresponding graph after each
2416 walk. So now increase it finally. */
2417 inc_irg_visited(get_const_code_irg());
2420 current_ir_graph = rem;
2424 dump_all_types (const char *suffix)
2426 FILE *f = vcg_open_name("All_types", suffix);
2427 dump_vcg_header(f, "All_types", NULL);
2428 type_walk(dump_type_info, NULL, f);
2429 inc_irg_visited(get_const_code_irg());
2434 dump_class_hierarchy (bool entities, const char *suffix)
2436 FILE *f = vcg_open_name("class_hierarchy", suffix);
2440 dump_vcg_header(f, "class_hierarchy", NULL);
2445 type_walk(dump_class_hierarchy_node, NULL, &env);
2449 /*---------------------------------------------------------------------*/
2450 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2452 /* dump_ir_block_graph */
2454 /* dump_type_graph */
2455 /* dump_ir_graph_w_types */
2456 /*---------------------------------------------------------------------*/
2458 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2459 int i, n_irgs = get_irp_n_irgs();
2460 for (i = 0; i < n_irgs; ++i) {
2461 dmp_grph(get_irp_irg(i), suffix);
2466 /*--------------------------------------------------------------------------------*
2467 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2468 * packed together in one subgraph/box *
2469 *--------------------------------------------------------------------------------*/
2471 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2472 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2474 ir_loop *son = NULL;
2476 /* Dump a new loop node. */
2477 dump_loop_node(F, loop);
2479 /* Dump the loop elements. */
2481 for(i = 0; i < get_loop_n_elements(loop); i++) {
2482 le = get_loop_element(loop, i);
2484 if (get_kind(son) == k_ir_loop) {
2486 /* We are a loop son -> Recurse */
2488 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2489 fprintf(F, "\" }\n");
2490 fprintf (F, "edge: {sourcename: \"");
2492 fprintf (F, "\" targetname: \"");
2494 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2495 loop_node_started = 0;
2497 dump_loop_son_edge(F, loop, son_number++);
2498 dump_loops_standalone(F, son);
2499 } else if (get_kind(son) == k_ir_node) {
2500 /* We are a loop node -> Collect firm nodes */
2502 ir_node *n = le.node;
2505 if (!loop_node_started) {
2506 /* Start a new node which contains all firm nodes of the current loop */
2507 fprintf (F, "node: { title: \"");
2509 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2510 loop_node_started = 1;
2516 bad |= dump_node_label(F, n);
2517 /* Causes indeterministic output: if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n)); */
2518 if (has_backedges(n)) fprintf(F, "\t loop head!");
2519 } else { /* for callgraph loop tree */
2521 assert(get_kind(son) == k_ir_graph);
2523 /* We are a loop node -> Collect firm graphs */
2524 n = (ir_graph *)le.node;
2525 if (!loop_node_started) {
2526 /* Start a new node which contains all firm nodes of the current loop */
2527 fprintf (F, "node: { title: \"");
2529 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2530 loop_node_started = 1;
2535 fprintf (F, " %s", get_irg_dump_name(n));
2536 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2540 if (loop_node_started) {
2541 fprintf(F, "\" }\n");
2542 fprintf (F, "edge: {sourcename: \"");
2544 fprintf (F, "\" targetname: \"");
2546 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2547 loop_node_started = 0;
2551 void dump_loop_tree(ir_graph *irg, const char *suffix)
2554 ir_graph *rem = current_ir_graph;
2555 int el_rem = edge_label;
2558 /* if a filter is set, dump only the irg's that match the filter */
2559 if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg)))) return;
2561 current_ir_graph = irg;
2563 f = vcg_open(irg, suffix, "-looptree");
2564 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2566 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2570 edge_label = el_rem;
2571 current_ir_graph = rem;
2574 void dump_callgraph_loop_tree(const char *suffix) {
2576 F = vcg_open_name("Callgraph_looptree", suffix);
2577 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2578 dump_loops_standalone(F, irp->outermost_cg_loop);
2583 /*-----------------------------------------------------------------------------*/
2584 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2585 /*-----------------------------------------------------------------------------*/
2587 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2588 int i, son_number = 0, node_number = 0;
2590 if (dump_loop_information_flag) dump_loop_node(F, loop);
2592 for (i = 0; i < get_loop_n_elements(loop); i++) {
2593 loop_element le = get_loop_element(loop, i);
2594 if (*(le.kind) == k_ir_loop) {
2595 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2597 collect_nodeloop(F, le.son, loopnodes);
2599 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2600 eset_insert(loopnodes, le.node);
2605 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2608 for(i = 0; i < get_loop_n_elements(loop); i++) {
2609 loop_element le = get_loop_element(loop, i);
2610 if (*(le.kind) == k_ir_loop) {
2612 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2614 if (is_Block(le.node)) start = 0; else start = -1;
2615 for (j = start; j < get_irn_arity(le.node); j++) {
2616 ir_node *pred = get_irn_n(le.node, j);
2617 if (!eset_contains(loopnodes, pred)) {
2618 eset_insert(extnodes, pred);
2619 if (!is_Block(pred)) {
2620 pred = get_nodes_block(pred);
2621 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2629 void dump_loop(ir_loop *l, const char *suffix) {
2632 eset *loopnodes = eset_create();
2633 eset *extnodes = eset_create();
2636 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2637 F = vcg_open_name (name, suffix);
2638 dump_vcg_header(F, name, NULL);
2640 /* collect all nodes to dump */
2641 collect_nodeloop(F, l, loopnodes);
2642 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2644 /* build block lists */
2645 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2646 set_irn_link(n, NULL);
2647 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2648 set_irn_link(n, NULL);
2649 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2651 b = get_nodes_block(n);
2652 set_irn_link(n, get_irn_link(b));
2655 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2657 b = get_nodes_block(n);
2658 set_irn_link(n, get_irn_link(b));
2662 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2664 fprintf(F, "graph: { title: \"");
2666 fprintf(F, "\" label: \"");
2667 dump_node_opcode(F, b);
2668 fprintf (F, " %ld", get_irn_node_nr(b));
2669 fprintf(F, "\" status:clustered color:yellow\n");
2671 /* dump the blocks edges */
2672 dump_ir_data_edges(F, b);
2674 /* dump the nodes that go into the block */
2675 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2676 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2678 overrule_nodecolor = NULL;
2679 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2682 /* Close the vcg information for the block */
2684 dump_const_node_local(F, b);
2687 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2689 fprintf(F, "graph: { title: \"");
2691 fprintf(F, "\" label: \"");
2692 dump_node_opcode(F, b);
2693 fprintf (F, " %ld", get_irn_node_nr(b));
2694 fprintf(F, "\" status:clustered color:lightblue\n");
2696 /* dump the nodes that go into the block */
2697 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2698 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2700 overrule_nodecolor = NULL;
2701 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2704 /* Close the vcg information for the block */
2706 dump_const_node_local(F, b);
2710 eset_destroy(loopnodes);
2711 eset_destroy(extnodes);