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.
18 #include "firm_common_t.h"
21 #include "irgraph_t.h"
31 #include "type_or_entity.h"
35 #include "callgraph.h"
45 void dump_chi_term(FILE *FL, ir_node *n);
46 void dump_state(FILE *FL, ir_node *n);
47 int get_opt_dump_abstvals(void);
48 typedef unsigned long SeqNo;
49 SeqNo get_Block_seqno(ir_node *n);
52 /* Attributes of nodes */
53 #define PRINT_DEFAULT_NODE_ATTR
54 #define DEFAULT_NODE_ATTR " "
55 #define DEFAULT_TYPE_ATTRIBUTE " "
56 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
58 /* Attributes of edges between Firm nodes */
59 #define INTRA_DATA_EDGE_ATTR "class:1 priority:50"
60 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
61 #define BLOCK_EDGE_ATTR "class:2 priority:50 linestyle:dotted"
62 #define CF_EDGE_ATTR "class:13 priority:60 color:red"
63 #define INTRA_MEM_EDGE_ATTR "class:14 priority:50 color:blue"
64 #define INTER_MEM_EDGE_ATTR "class:17 priority:10 color:blue"
65 #define DOMINATOR_EDGE_ATTR "class:15 color:red"
67 #define BACK_EDGE_ATTR "linestyle:dashed "
69 /* Attributes of edges between Firm nodes and type/entity nodes */
70 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
72 /* Attributes of edges in type/entity graphs. */
73 #define TYPE_METH_NODE_ATTR "color: lightyellow"
74 #define TYPE_CLASS_NODE_ATTR "color: green"
75 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
76 #define ENTITY_NODE_ATTR "color: yellow"
77 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
78 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
79 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
80 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
81 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
82 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
83 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
84 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
85 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
86 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
87 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
88 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
89 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
90 #define ENUM_ITEM_NODE_ATTR "color: green"
91 #define CALLGRAPH_EDGE_ATTR "calls"
93 #if DEBUG_libfirm && NODEID_AS_LABEL
94 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
95 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
96 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
97 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
98 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
99 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
100 #define PRINT_ITEMID(X,Y) fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
103 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
104 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
105 #define PRINT_ENTID(X) fprintf(F, "e%p", (void *)(X))
106 #define PRINT_IRGID(X) fprintf(F, "g%p",(void *)(X))
107 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
108 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
109 #define PRINT_ITEMID(X,Y) fprintf(F, "i%pT%d", (void *) (X), (Y))
113 /* basis for a color range for vcg */
114 static int n_colors = 0;
115 static int base_color = 0;
117 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
120 return get_mode_name(mode);
125 static const char *get_type_name_ex(type *tp, int *bad)
128 return get_type_name(tp);
133 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
138 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
139 fprintf(F, " targetname: "); PRINT_TYPEID(T);
140 vfprintf(F, fmt, ap);
145 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
150 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
151 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
152 vfprintf(F, fmt, ap);
157 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
163 fprintf(F, "backedge: { sourcename: \"");
165 fprintf(F, "edge: { sourcename: \"");
167 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
168 vfprintf(F, fmt, ap);
173 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
178 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
179 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
180 vfprintf(F, fmt, ap);
185 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
190 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
191 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
192 vfprintf(F, fmt, ap);
197 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
202 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
203 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
205 vfprintf(F, fmt, ap);
210 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
215 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
216 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
217 vfprintf(F, fmt, ap);
222 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
227 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
228 fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
229 vfprintf(F, fmt, ap);
234 /*******************************************************************/
235 /* global and ahead declarations */
236 /*******************************************************************/
238 static void dump_whole_node(ir_node *n, void *env);
239 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
241 /*******************************************************************/
242 /* Helper functions. */
243 /*******************************************************************/
245 /* Use private link attr to be able to call dumper anywhere without
246 destroying link fields. */
248 static pmap *irdump_link_map = NULL;
250 static void init_irdump(void) {
251 /* We need a new, empty map. */
252 if (irdump_link_map) pmap_destroy(irdump_link_map);
253 irdump_link_map = pmap_create();
257 void *ird_get_irn_link(ir_node *n) {
259 if (!irdump_link_map) return NULL;
261 if (pmap_contains(irdump_link_map, (void *)n))
262 res = pmap_get(irdump_link_map, (void *)n);
266 void ird_set_irn_link(ir_node *n, void *x) {
267 if (!irdump_link_map) init_irdump();
268 pmap_insert(irdump_link_map, (void *)n, x);
271 void *ird_get_irg_link(ir_graph *irg) {
273 if (!irdump_link_map) return NULL;
275 if (pmap_contains(irdump_link_map, (void *)irg))
276 res = pmap_get(irdump_link_map, (void *)irg);
280 void ird_set_irg_link(ir_graph *irg, void *x) {
281 if (!irdump_link_map) init_irdump();
282 pmap_insert(irdump_link_map, (void *)irg, x);
285 static void clear_link(ir_node * node, void * env) {
286 ird_set_irn_link(node, NULL);
290 static int node_floats(ir_node *n) {
291 return ((get_op_pinned(get_irn_op(n)) == op_pin_state_floats) &&
292 (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
295 static const char *get_ent_dump_name(entity *ent) {
297 return "<NULL entity>";
298 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
299 if (ent->ld_name) return get_id_str(ent->ld_name);
300 return get_id_str(ent->name);
303 static const char *get_irg_dump_name(ir_graph *irg) {
304 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
305 entity *ent = get_irg_entity(irg);
306 return get_ent_dump_name(ent);
309 static void collect_node(ir_node * node, void *env) {
312 || get_irn_op(node) == op_Bad
313 || get_irn_op(node) == op_Unknown) {
314 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
315 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
316 ARR_APP1(ir_node *, arr, node);
317 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
319 ir_node * block = get_nodes_block(node);
320 ird_set_irn_link(node, ird_get_irn_link(block));
321 ird_set_irn_link(block, node);
325 /** Construct lists to walk ir block-wise.
327 * Collects all blocks, nodes not op_pin_state_pinned,
328 * Bad and Unknown into a flexible array in link field of
329 * irg they belong to. Sets the irg link field to NULL in all
330 * graphs not visited.
331 * Free the list with DEL_ARR_F. */
332 static ir_node ** construct_block_lists(ir_graph *irg) {
333 int i, rem_view = interprocedural_view;
334 ir_graph *rem = current_ir_graph;
335 current_ir_graph = irg;
337 for (i = 0; i < get_irp_n_irgs(); i++)
338 ird_set_irg_link(get_irp_irg(i), NULL);
340 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
342 /* Collect also EndReg and EndExcept. We do not want to change the walker. */
343 interprocedural_view = 0;
344 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
345 irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
346 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
347 irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
348 interprocedural_view = rem_view;
350 current_ir_graph = rem;
351 return ird_get_irg_link(irg);
354 /*******************************************************************/
355 /* flags to steer output */
356 /*******************************************************************/
358 const char *dump_file_filter = "";
360 /* A compiler option to turn off edge labels */
362 /* A compiler option to turn off dumping values of constant entities */
363 int const_entities = 1;
364 /* A compiler option to dump the keep alive edges */
365 int dump_keepalive = 0;
366 /* Compiler options to dump analysis information in dump_ir_graph */
367 int dump_out_edge_flag = 0;
368 int dump_dominator_information_flag = 0;
369 int dump_loop_information_flag = 0;
370 int dump_backedge_information_flag = 1;
371 int dump_const_local = 0;
372 bool opt_dump_analysed_type_info = 1;
373 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
375 char* overrule_nodecolor = NULL;
377 INLINE bool get_opt_dump_const_local(void) {
378 if (!dump_out_edge_flag && !dump_loop_information_flag)
379 return dump_const_local;
384 void only_dump_method_with_name(ident *name) {
385 dump_file_filter = get_id_str(name);
389 /* To turn off display of edge labels. Edge labels offen cause xvcg to
390 abort with a segmentation fault. */
391 void turn_off_edge_labels(void) {
395 void dump_consts_local(bool b) {
396 dump_const_local = b;
399 void turn_off_constant_entity_values(void) {
403 void dump_keepalive_edges(bool b) {
407 bool get_opt_dump_keepalive_edges(void) {
408 return dump_keepalive;
411 void dump_out_edges(void) {
412 dump_out_edge_flag = 1;
415 void dump_dominator_information(void) {
416 dump_dominator_information_flag = 1;
419 void dump_loop_information(void) {
420 dump_loop_information_flag = 1;
423 void dont_dump_loop_information(void) {
424 dump_loop_information_flag = 0;
427 void dump_backedge_information(bool b) {
428 dump_backedge_information_flag = b;
431 /* Dump the information of type field specified in ana/irtypeinfo.h.
432 * If the flag is set, the type name is output in [] in the node label,
433 * else it is output as info.
435 void dump_analysed_type_info(bool b) {
436 opt_dump_analysed_type_info = b;
439 void dump_pointer_values_to_info(bool b) {
440 opt_dump_pointer_values_to_info = b;
443 /*-----------------------------------------------------------------*/
444 /* Routines to dump information about a single ir node. */
445 /*-----------------------------------------------------------------*/
448 dump_node_opcode(FILE *F, ir_node *n)
452 switch(get_irn_opcode(n)) {
457 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
458 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
463 if (get_SymConst_kind(n) == symconst_addr_name) {
464 /* don't use get_SymConst_ptr_info as it mangles the name. */
465 fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
466 } else if (get_SymConst_kind(n) == symconst_addr_ent) {
467 assert(get_SymConst_entity(n));
468 assert(is_entity(get_SymConst_entity(n)));
469 fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
471 assert(get_kind(get_SymConst_type(n)) == k_type);
472 assert(get_type_ident(get_SymConst_type(n)));
473 fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
474 if (get_SymConst_kind(n) == symconst_type_tag)
482 if (!interprocedural_view) fprintf(F, "Proj'");
483 else goto default_case;
487 ir_node *pred = get_Proj_pred(n);
489 if (get_irn_opcode(pred) == iro_Cond
490 && get_Proj_proj(n) == get_Cond_defaultProj(pred)
491 && get_irn_mode(get_Cond_selector(pred)) != mode_b)
492 fprintf (F, "defProj");
494 * else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
495 * fprintf (F, "Arg");
504 if (interprocedural_view) {
505 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
510 case iro_CallBegin: {
511 ir_node *addr = get_CallBegin_ptr(n);
513 if (get_irn_op(addr) == op_Sel)
514 ent = get_Sel_entity(addr);
515 else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
516 ent = get_SymConst_entity(addr);
517 fprintf (F, "%s", get_irn_opname(n));
518 if (ent) fprintf (F, " %s", get_entity_name(ent));
524 fprintf (F, "%s", get_irn_opname(n));
532 dump_node_mode(FILE *F, ir_node *n)
536 switch (get_irn_opcode(n)) {
555 fprintf(F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
563 static int dump_node_typeinfo(FILE *F, ir_node *n) {
566 if (opt_dump_analysed_type_info) {
567 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
568 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
569 type *tp = get_irn_type(n);
571 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
580 dump_node_nodeattr(FILE *F, ir_node *n)
584 switch (get_irn_opcode(n)) {
586 if (false && interprocedural_view) {
587 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
591 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
592 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
594 fprintf (F, "%ld", get_Proj_proj(n));
598 fprintf (F, "%ld", get_Filter_proj(n));
601 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
604 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
607 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
617 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
620 fprintf(F, "color: red");
623 switch (get_irn_opcode(n)) {
630 fprintf (F, "color: blue");
633 fprintf (F, "color: lightyellow");
636 fprintf (F, "color: green");
642 fprintf (F, "color: yellow");
645 PRINT_DEFAULT_NODE_ATTR;
648 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
651 static INLINE int dump_node_info(FILE *F, ir_node *n)
657 fprintf (F, " info1: \"");
658 if (opt_dump_pointer_values_to_info)
659 fprintf (F, "addr: %p \n", (void *)n);
660 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
661 fprintf (F, "visited: %ld \n", get_irn_visited(n));
662 irg = get_irn_irg(n);
663 if (irg != get_const_code_irg())
664 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
666 if (get_op_pinned(get_irn_op(n)) == op_pin_state_floats &&
667 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
668 fprintf(F, "node was pinned in ");
669 dump_node_opcode(F, get_nodes_block(n));
670 fprintf(F, " %ld\n", get_irn_node_nr(n));
674 /* show all predecessor nodes */
675 fprintf(F, "pred nodes: \n");
678 dump_node_opcode(F, get_nodes_block(n));
679 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
681 for ( i = 0; i < get_irn_arity(n); ++i) {
682 fprintf(F, " %d: ", i);
683 dump_node_opcode(F, get_irn_n(n, i));
684 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
688 fprintf(F, "arity: %d", get_irn_arity(n));
689 if ((get_irn_op(n) == op_Block) ||
690 (get_irn_op(n) == op_Phi) ||
691 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
692 fprintf(F, " backedges:");
694 for (i = 0; i < get_irn_arity(n); i++)
695 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
699 /* Loop node Someone else please tell me what's wrong ...
700 if (get_irn_loop(n)) {
701 ir_loop *loop = get_irn_loop(n);
703 fprintf(F, " in loop %d with depth %d\n",
704 get_loop_loop_nr(loop), get_loop_depth(loop));
709 switch (get_irn_opcode(n)) {
711 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
712 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
713 for (i = 0; i < get_method_n_params(tp); ++i)
714 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
717 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
720 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
723 entity *ent = get_Sel_entity(n);
726 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
727 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
730 fprintf(F, "<NULL entity>\n");
735 type *tp = get_Call_type(n);
736 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
737 for (i = 0; i < get_method_n_params(tp); ++i)
738 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
739 for (i = 0; i < get_method_n_ress(tp); ++i)
740 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
741 if (0 && Call_has_callees(n)) {
742 fprintf(F, "possible callees: \n");
743 for (i = 0; i < get_Call_n_callees(n); i++) {
744 if (!get_Call_callee(n, i)) {
745 fprintf(F, " %d external method\n", i);
747 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
752 case iro_CallBegin: {
753 ir_node *call = get_CallBegin_call(n);
754 if (Call_has_callees(call)) {
755 fprintf(F, "possible callees: \n");
756 for (i = 0; i < get_Call_n_callees(call); i++) {
757 if (!get_Call_callee(call, i)) {
758 fprintf(F, " %d external method\n", i);
760 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
766 if (!interprocedural_view) {
767 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
768 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
769 for (i = 0; i < get_method_n_ress(tp); ++i)
770 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
774 type *tp = get_Const_type(n);
775 assert(tp != none_type);
776 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
779 switch(get_SymConst_kind(n)) {
780 case symconst_addr_name:
781 fprintf(F, "kind addr_name\n");
783 case symconst_addr_ent:
784 fprintf(F, "kind addr_ent\n");
786 case symconst_type_tag:
787 fprintf(F, "kind type_tag\n");
790 fprintf(F, "kind size\n");
796 if (interprocedural_view) {
797 fprintf(F, "intra predecessor nodes:\n");
798 for (i = 0; i < get_irn_intra_arity(n); i++) {
799 ir_node *pred = get_irn_intra_n(n, i);
800 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
803 fprintf(F, "inter predecessor nodes:\n");
804 for (i = 0; i < get_irn_inter_arity(n); i++) {
805 ir_node *pred = get_irn_inter_n(n, i);
806 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
807 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
814 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
815 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
816 if (get_irn_type(n) != none_type)
817 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
826 bool is_constlike_node(ir_node *n) {
827 ir_op *op = get_irn_op(n);
828 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
832 /* outputs the predecessors of n, that are constants, local. I.e.,
833 generates a copy of the constant predecessors for each node called with. */
834 static void dump_const_node_local(FILE *F, ir_node *n) {
836 if (!get_opt_dump_const_local()) return;
838 /* Use visited flag to avoid outputting nodes twice.
839 initialize it first. */
840 for (i = 0; i < get_irn_arity(n); i++) {
841 ir_node *con = get_irn_n(n, i);
842 if (is_constlike_node(con)) {
843 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
847 for (i = 0; i < get_irn_arity(n); i++) {
848 ir_node *con = get_irn_n(n, i);
849 if (is_constlike_node(con) && irn_not_visited(con)) {
852 mark_irn_visited(con);
853 /* Generate a new name for the node by appending the names of
855 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
856 fprintf(F, " label: \"");
857 bad |= dump_node_opcode(F, con);
858 bad |= dump_node_mode(F, con);
859 bad |= dump_node_typeinfo(F, con);
861 bad |= dump_node_nodeattr(F, con);
862 fprintf(F, " %ld", get_irn_node_nr(con));
864 bad |= dump_node_info(F, con);
865 dump_node_vcgattr(F, con, bad);
871 static void INLINE print_node_error(FILE *F, const char *p)
876 fprintf (F, " info2: \"%s\"", p);
879 static void dump_node(FILE *F, ir_node *n)
884 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
886 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
888 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
889 bad |= dump_node_opcode(F, n);
890 bad |= dump_node_mode(F, n);
891 bad |= dump_node_typeinfo(F, n);
893 bad |= dump_node_nodeattr(F, n);
894 fprintf(F, " %ld", get_irn_node_nr(n));
896 bad |= dump_node_info(F, n);
897 print_node_error(F, p);
898 dump_node_vcgattr(F, n, bad);
900 dump_const_node_local(F, n);
907 /* dump the edge to the block this node belongs to */
909 dump_ir_block_edge(FILE *F, ir_node *n) {
910 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
911 if (is_no_Block(n)) {
912 ir_node *block = get_nodes_block(n);
914 fprintf (F, "edge: { sourcename: \"");
916 fprintf (F, "\" targetname: ");
917 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
918 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
923 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
924 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
925 fprintf (F, INTRA_DATA_EDGE_ATTR);
927 fprintf (F, INTER_DATA_EDGE_ATTR);
931 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
932 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
933 fprintf (F, INTRA_MEM_EDGE_ATTR);
935 fprintf (F, INTER_MEM_EDGE_ATTR);
939 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
942 if (dump_backedge_information_flag && is_backedge(from, to))
943 fprintf (F, BACK_EDGE_ATTR);
945 switch (get_irn_opcode(from)) {
947 fprintf (F, CF_EDGE_ATTR);
949 case iro_Start: break;
952 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
953 fprintf (F, CF_EDGE_ATTR);
954 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
955 fprintf (F, INTER_MEM_EDGE_ATTR);
963 print_data_edge_vcgattr(F, from, to);
968 print_mem_edge_vcgattr(F, from, to);
970 print_data_edge_vcgattr(F, from, to);
974 print_data_edge_vcgattr(F, from, to);
979 print_mem_edge_vcgattr(F, from, to);
981 print_data_edge_vcgattr(F, from, to);
988 print_data_edge_vcgattr(F, from, to);
995 print_mem_edge_vcgattr(F, from, to);
997 print_data_edge_vcgattr(F, from, to);
1009 print_data_edge_vcgattr(F, from, to);
1012 if (get_irn_modecode(from) == irm_M)
1013 fprintf (F, INTER_MEM_EDGE_ATTR);
1015 print_data_edge_vcgattr(F, from, to);
1022 print_mem_edge_vcgattr(F, from, to);
1024 print_data_edge_vcgattr(F, from, to);
1027 print_mem_edge_vcgattr(F, from, to);
1029 case iro_Tuple: break;
1032 switch (get_irn_modecode(from)) {
1034 fprintf (F, CF_EDGE_ATTR);
1037 fprintf (F, INTER_MEM_EDGE_ATTR);
1040 print_data_edge_vcgattr(F, from, to);
1044 case iro_Bad: break;
1045 case iro_Unknown: break;
1047 switch (get_irn_modecode(from)) {
1049 fprintf (F, INTRA_MEM_EDGE_ATTR);
1052 fprintf (F, CF_EDGE_ATTR);
1055 print_data_edge_vcgattr(F, from, to);
1063 /* dump edges to our inputs */
1065 dump_ir_data_edges(FILE *F, ir_node *n) {
1066 int i, visited = get_irn_visited(n);
1068 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1071 for (i = 0; i < get_irn_arity(n); i++) {
1072 ir_node * pred = get_irn_n(n, i);
1075 if ((interprocedural_view && get_irn_visited(pred) < visited))
1076 continue; /* pred not dumped */
1078 if (dump_backedge_information_flag && is_backedge(n, i))
1079 fprintf (F, "backedge: {sourcename: \"");
1081 fprintf (F, "edge: {sourcename: \"");
1083 fprintf (F, "\" targetname: ");
1084 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1085 PRINT_CONSTID(n, pred);
1087 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1089 fprintf (F, " label: \"%d\" ", i);
1090 print_edge_vcgattr(F, n, i);
1095 /** Dumps a node and its edges but not the block edge
1098 dump_node_wo_blockedge (ir_node *n, void *env) {
1101 dump_ir_data_edges(F, n);
1104 /** Dumps a node and its edges.
1107 dump_whole_node (ir_node *n, void *env) {
1109 dump_node_wo_blockedge(n, env);
1110 if (!node_floats(n)) dump_ir_block_edge(F, n);
1114 dump_const_node(ir_node *n, void *env) {
1115 if (is_Block(n)) return;
1116 dump_node_wo_blockedge(n, env);
1119 /***********************************************************************/
1120 /* the following routines dump the nodes/irgs bracketed to graphs. */
1121 /***********************************************************************/
1123 /** Dumps a constant expression as entity initializer, array bound ...
1125 static void dump_const_expression(FILE *F, ir_node *value) {
1126 ir_graph *rem = current_ir_graph;
1127 int rem_dump_const_local = dump_const_local;
1128 dump_const_local = 0;
1129 current_ir_graph = get_const_code_irg();
1130 irg_walk(value, dump_const_node, NULL, F);
1131 /* Decrease visited flag so that we walk with the same flag for the next
1132 expresssion. This guarantees that we don't dump the same node twice,
1133 as for const expressions cse is performed to save memory. */
1134 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1135 current_ir_graph = rem;
1136 dump_const_local = rem_dump_const_local;
1139 /** Dump a block as graph containing its nodes.
1141 * Expects to find nodes belonging to the block as list in its
1143 * Dumps the edges of all nodes including itself. */
1145 dump_whole_block(FILE *F, ir_node *block) {
1147 assert(is_Block(block));
1149 fprintf(F, "graph: { title: \"");
1150 PRINT_NODEID(block);
1151 fprintf(F, "\" label: \"");
1152 dump_node_opcode(F, block);
1153 fprintf (F, " %ld", get_irn_node_nr(block));
1155 if (get_opt_dump_abstvals())
1156 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1158 fprintf(F, "\" status:clustered color:%s \n",
1159 get_Block_matured(block) ? "yellow" : "red");
1161 /* dump the blocks edges */
1162 dump_ir_data_edges(F, block);
1164 /* dump the nodes that go into the block */
1165 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1167 dump_ir_data_edges(F, node);
1170 /* Close the vcg information for the block */
1172 dump_const_node_local(F, block);
1174 dump_chi_term(F, block);
1179 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1180 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1182 dump_block_graph(FILE *F, ir_graph *irg) {
1184 ir_graph *rem = current_ir_graph;
1185 ir_node **arr = ird_get_irg_link(irg);
1186 current_ir_graph = irg;
1188 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1189 ir_node * node = arr[i];
1190 if (is_Block(node)) {
1191 /* Dumps the block and all the nodes in the block, which are to
1192 be found in Block->link. */
1193 dump_whole_block(F, node);
1195 /* Nodes that are not in a Block. */
1197 dump_ir_data_edges(F, node);
1201 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1202 dump_loop_nodes_into_graph(F, irg);
1204 current_ir_graph = rem;
1207 /** Dumps an irg as a graph.
1208 * If interprocedural view edges can point to nodes out of this graph.
1210 static void dump_graph(FILE *F, ir_graph *irg) {
1212 fprintf(F, "graph: { title: \"");
1214 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1215 get_ent_dump_name(get_irg_entity(irg)));
1217 dump_block_graph(F, irg);
1219 /* Close the vcg information for the irg */
1220 fprintf(F, "}\n\n");
1223 /*******************************************************************/
1224 /* Basic type and entity nodes and edges. */
1225 /*******************************************************************/
1227 /* dumps the edges between nodes and their type or entity attributes. */
1228 static void dump_node2type_edges(ir_node *n, void *env)
1233 switch (get_irn_opcode(n)) {
1235 /* @@@ some consts have an entity */
1238 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1239 || (get_SymConst_kind(n) ==symconst_size))
1241 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1245 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1248 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1251 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1254 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1257 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1265 static int print_type_info(FILE *F, type *tp) {
1268 if (get_type_state(tp) == layout_undefined) {
1269 fprintf(F, "state: layout_undefined\n");
1271 fprintf(F, "state: layout_fixed,\n");
1273 if (get_type_mode(tp))
1274 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1275 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1280 static void print_typespecific_info(FILE *F, type *tp) {
1281 switch (get_type_tpop_code(tp)) {
1284 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1291 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1292 fprintf(F, "params: %d\n", get_method_n_params(tp));
1293 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1301 case tpo_enumeration:
1315 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1316 switch (get_type_tpop_code(tp)) {
1319 if (peculiarity_existent == get_class_peculiarity(tp))
1320 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1322 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1326 fprintf (F, " " TYPE_METH_NODE_ATTR);
1337 case tpo_enumeration:
1350 static int print_type_node(FILE *F, type *tp)
1354 fprintf (F, "node: {title: ");
1356 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1357 fprintf (F, " info1: \"");
1358 bad |= print_type_info(F, tp);
1359 print_typespecific_info(F, tp);
1361 print_typespecific_vcgattr(F, tp);
1367 #define X(a) case a: fprintf(F, #a); break
1368 void dump_entity_node(FILE *F, entity *ent, int color)
1370 fprintf (F, "node: {title: \"");
1371 PRINT_ENTID(ent); fprintf(F, "\"");
1372 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1373 fprintf (F, "label: ");
1374 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1376 fprintf(F, "color: %d", color);
1378 fprintf (F, ENTITY_NODE_ATTR);
1379 fprintf (F, "\n info1: \"");
1381 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1383 fprintf(F, "\"\n}\n");
1387 static void dump_enum_item(FILE *F, type *tp, int pos)
1390 ident *id = get_enumeration_nameid(tp, pos);
1391 tarval *tv = get_enumeration_enum(tp, pos);
1393 tarval_snprintf(buf, sizeof(buf), tv);
1394 fprintf (F, "node: {title: \"");
1395 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1396 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1397 fprintf (F, "label: ");
1398 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1399 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1402 /* dumps a type or entity and it's edges. */
1404 dump_type_info(type_or_ent *tore, void *env) {
1406 int i = 0; /* to shutup gcc */
1408 /* dump this type or entity */
1410 switch (get_kind(tore)) {
1413 entity *ent = (entity *)tore;
1416 dump_entity_node(F, ent, 0);
1418 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1419 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1420 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1421 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1422 if(is_class_type(get_entity_owner(ent))) {
1423 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1424 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1426 /* attached subgraphs */
1427 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1428 if (is_atomic_entity(ent)) {
1429 value = get_atomic_ent_value(ent);
1431 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1432 /* DDMN(value); $$$ */
1433 dump_const_expression(F, value);
1436 if (is_compound_entity(ent)) {
1437 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1438 value = get_compound_ent_value(ent, i);
1440 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1441 dump_const_expression(F, value);
1442 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1444 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1445 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1446 get_compound_ent_value_member(ent, i), i);
1455 type *tp = (type *)tore;
1456 print_type_node(F, tp);
1457 /* and now the edges */
1458 switch (get_type_tpop_code(tp)) {
1461 for (i=0; i < get_class_n_supertypes(tp); i++)
1462 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1463 for (i=0; i < get_class_n_members(tp); i++)
1464 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1468 for (i=0; i < get_struct_n_members(tp); i++)
1469 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1473 for (i = 0; i < get_method_n_params(tp); i++)
1474 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1475 for (i = 0; i < get_method_n_ress(tp); i++)
1476 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1480 for (i = 0; i < get_union_n_members(tp); i++)
1481 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1485 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1486 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1487 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1488 ir_node *upper = get_array_upper_bound(tp, i);
1489 ir_node *lower = get_array_lower_bound(tp, i);
1490 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1491 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1492 dump_const_expression(F, upper);
1493 dump_const_expression(F, lower);
1497 case tpo_enumeration:
1499 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1500 dump_enum_item(F, tp, i);
1501 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1506 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1514 break; /* case k_type */
1517 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1519 } /* switch kind_or_entity */
1522 typedef struct _h_env {
1527 /** For dumping class hierarchies.
1528 * Dumps a class type node and a superclass edge.
1529 * If env->dump_ent dumps entities of classes and overwrites edges.
1532 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1535 int i = 0; /* to shutup gcc */
1537 /* dump this type or entity */
1538 switch (get_kind(tore)) {
1540 entity *ent = (entity *)tore;
1541 if (get_entity_owner(ent) == get_glob_type()) break;
1542 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1543 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1545 dump_entity_node(F, ent, 0);
1547 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1548 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1549 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1551 } break; /* case k_entity */
1554 type *tp = (type *)tore;
1555 if (tp == get_glob_type()) break;
1556 switch (get_type_tpop_code(tp)) {
1558 print_type_node(F, tp);
1559 /* and now the edges */
1560 for (i=0; i < get_class_n_supertypes(tp); i++)
1562 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1568 break; /* case k_type */
1571 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1573 } /* switch kind_or_entity */
1576 /*******************************************************************/
1577 /* dump analysis information that is expressed in graph terms. */
1578 /*******************************************************************/
1580 /* dump out edges */
1582 dump_out_edge(ir_node *n, void *env) {
1585 for (i = 0; i < get_irn_n_outs(n); i++) {
1586 assert(get_irn_out(n, i));
1587 fprintf (F, "edge: {sourcename: \"");
1589 fprintf (F, "\" targetname: \"");
1590 PRINT_NODEID(get_irn_out(n, i));
1591 fprintf (F, "\" color: red linestyle: dashed");
1597 dump_loop_label(FILE *F, ir_loop *loop) {
1598 fprintf (F, "loop %d, %d sons, %d nodes",
1599 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1602 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1603 fprintf (F, " info1: \"");
1604 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1605 #if DEBUG_libfirm /* GL @@@ debug analyses */
1606 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1612 dump_loop_node(FILE *F, ir_loop *loop) {
1613 fprintf (F, "node: {title: \"");
1615 fprintf (F, "\" label: \"");
1616 dump_loop_label(F, loop);
1618 dump_loop_info(F, loop);
1624 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1626 fprintf (F, "edge: {sourcename: \"");
1628 fprintf (F, "\" targetname: \"");
1629 PRINT_NODEID(get_loop_node(loop, i));
1630 fprintf (F, "\" color: green");
1635 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1637 fprintf (F, "edge: {sourcename: \"");
1639 fprintf (F, "\" targetname: \"");
1640 PRINT_LOOPID(get_loop_son(loop, i));
1641 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1642 get_loop_element_pos(loop, get_loop_son(loop, i)));
1646 void dump_loops(FILE *F, ir_loop *loop) {
1648 /* dump this loop node */
1649 dump_loop_node(F, loop);
1651 /* dump edges to nodes in loop -- only if it is a real loop */
1652 if (get_loop_depth(loop) != 0) {
1653 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1654 dump_loop_node_edge(F, loop, i);
1657 for (i = 0; i < get_loop_n_sons(loop); i++) {
1658 dump_loops(F, get_loop_son(loop, i));
1659 dump_loop_son_edge(F, loop, i);
1664 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1665 ir_graph *rem = current_ir_graph;
1666 current_ir_graph = irg;
1668 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1670 current_ir_graph = rem;
1675 * dumps the VCG header
1678 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1687 if (!orientation) orientation = "bottom_to_top";
1691 "graph: { title: \"ir graph of %s\"\n"
1692 "display_edge_labels: %s\n"
1693 "layoutalgorithm: mindepth\n"
1694 "manhattan_edges: yes\n"
1695 "port_sharing: no\n"
1697 "classname 1: \"intrablock Data\"\n"
1698 "classname 16: \"interblock Data\"\n"
1699 "classname 2: \"Block\"\n"
1700 "classname 13: \"Control Flow\"\n"
1701 "classname 14: \"intrablock Memory\"\n"
1702 "classname 17: \"interblock Memory\"\n"
1703 "classname 15: \"Dominators\"\n"
1704 "classname 3: \"Entity type\"\n"
1705 "classname 4: \"Entity owner\"\n"
1706 "classname 5: \"Method Param\"\n"
1707 "classname 6: \"Method Res\"\n"
1708 "classname 7: \"Super\"\n"
1709 "classname 8: \"Union\"\n"
1710 "classname 9: \"Points-to\"\n"
1711 "classname 10: \"Array Element Type\"\n"
1712 "classname 11: \"Overwrites\"\n"
1713 "classname 12: \"Member\"\n"
1714 "infoname 1: \"Attribute\"\n"
1715 "infoname 2: \"Verification errors\"\n",
1716 name, label, orientation);
1718 /* don't use all, the range is too whith/black. */
1722 "colorentry 100: 0 0 0\n"
1723 "colorentry 101: 20 0 0\n"
1724 "colorentry 102: 40 0 0\n"
1725 "colorentry 103: 60 0 0\n"
1726 "colorentry 104: 80 0 0\n"
1727 "colorentry 105: 100 0 0\n"
1728 "colorentry 106: 120 0 0\n"
1729 "colorentry 107: 140 0 0\n"
1730 "colorentry 108: 150 0 0\n"
1731 "colorentry 109: 180 0 0\n"
1732 "colorentry 110: 200 0 0\n"
1733 "colorentry 111: 220 0 0\n"
1734 "colorentry 112: 240 0 0\n"
1735 "colorentry 113: 255 0 0\n"
1736 "colorentry 113: 255 20 20\n"
1737 "colorentry 114: 255 40 40\n"
1738 "colorentry 115: 255 60 60\n"
1739 "colorentry 116: 255 80 80\n"
1740 "colorentry 117: 255 100 100\n"
1741 "colorentry 118: 255 120 120\n"
1742 "colorentry 119: 255 140 140\n"
1743 "colorentry 120: 255 150 150\n"
1744 "colorentry 121: 255 180 180\n"
1745 "colorentry 122: 255 200 200\n"
1746 "colorentry 123: 255 220 220\n"
1747 "colorentry 124: 255 240 240\n"
1748 "colorentry 125: 255 250 250\n"
1751 fprintf (F, "\n"); /* a separator */
1757 * @param irg The graph to be dumped
1758 * @param suffix1 first filename suffix
1759 * @param suffix2 second filename suffix
1761 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1763 const char *nm = get_irg_dump_name(irg);
1764 int len = strlen(nm), i, j;
1765 char *fname; /* filename to put the vcg information in */
1767 if (!suffix1) suffix1 = "";
1768 if (!suffix2) suffix2 = "";
1770 /* open file for vcg graph */
1771 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1773 /* strncpy (fname, nm, len); */ /* copy the filename */
1775 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1777 fname[j] = '@'; j++; fname[j] = '1'; j++;
1778 } else if (nm[i] == '@') {
1779 fname[j] = '@'; j++; fname[j] = '2'; j++;
1781 fname[j] = nm[i]; j++;
1785 strcat (fname, suffix1); /* append file suffix */
1786 strcat (fname, suffix2); /* append file suffix */
1787 strcat (fname, ".vcg"); /* append the .vcg suffix */
1788 F = fopen (fname, "w"); /* open file for writing */
1790 panic("cannot open %s for writing (%m)", fname); /* not reached */
1800 * @param irg The graph to be dumped
1801 * @param suffix filename suffix
1803 static FILE *vcg_open_name (const char *name, const char *suffix) {
1805 char *fname; /* filename to put the vcg information in */
1806 int i, j, len = strlen(name);
1808 if (!suffix) suffix = "";
1810 /** open file for vcg graph */
1811 fname = malloc (len * 2 + 5 + strlen(suffix));
1812 /* strcpy (fname, name);*/ /* copy the filename */
1814 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1815 if (name[i] == '/') {
1816 fname[j] = '@'; j++; fname[j] = '1'; j++;
1817 } else if (name[i] == '@') {
1818 fname[j] = '@'; j++; fname[j] = '2'; j++;
1820 fname[j] = name[i]; j++;
1824 strcat (fname, suffix);
1825 strcat (fname, ".vcg"); /* append the .vcg suffix */
1826 F = fopen (fname, "w"); /* open file for writing */
1828 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1836 * Dumps the vcg file footer
1838 static INLINE void dump_vcg_footer (FILE *F) {
1843 * close the vcg file
1846 vcg_close (FILE *F) {
1847 dump_vcg_footer(F); /* print footer */
1848 fclose (F); /* close vcg file */
1851 /************************************************************************/
1852 /************************************************************************/
1853 /* Routines that dump all or parts of the firm representation to a file */
1854 /************************************************************************/
1855 /************************************************************************/
1857 /************************************************************************/
1858 /* Dump ir graphs, differnt formats and additional information. */
1859 /************************************************************************/
1861 /** Routine to dump a graph, blocks as conventional nodes.
1864 dump_ir_graph (ir_graph *irg, const char *suffix )
1869 rem = current_ir_graph;
1871 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1872 current_ir_graph = irg;
1873 if (interprocedural_view) suffix1 = "-pure-ip";
1874 else suffix1 = "-pure";
1875 f = vcg_open(irg, suffix, suffix1);
1876 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1878 /* walk over the graph */
1879 /* dump_whole_node must be called in post visiting predecessors */
1880 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1882 /* dump the out edges in a separate walk */
1883 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1884 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1889 current_ir_graph = rem;
1894 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1900 if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1901 if (interprocedural_view) suffix1 = "-ip";
1903 f = vcg_open(irg, suffix, suffix1);
1904 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1906 construct_block_lists(irg);
1908 for (i = 0; i < get_irp_n_irgs(); i++) {
1909 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1911 dump_graph(f, get_irp_irg(i));
1919 /** dumps a graph with type information
1922 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1925 ir_graph *rem = current_ir_graph;
1928 /* if a filter is set, dump only the irg's that match the filter */
1929 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1932 current_ir_graph = irg;
1934 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1935 else suffix1 = "-pure-wtypes";
1936 f = vcg_open(irg,suffix, suffix1);
1937 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1939 /* dump common ir graph */
1940 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1941 /* dump type info */
1942 type_walk_irg(irg, dump_type_info, NULL, f);
1943 inc_irg_visited(get_const_code_irg());
1944 /* dump edges from graph to type info */
1945 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1948 current_ir_graph = rem;
1952 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1957 ir_graph *rem = current_ir_graph;
1959 /* if a filter is set, dump only the irg's that match the filter */
1960 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1963 if (interprocedural_view) suffix1 = "-wtypes-ip";
1964 else suffix1 = "-wtypes";
1965 f = vcg_open(irg, suffix, suffix1);
1966 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1968 /* dump common blocked ir graph */
1969 construct_block_lists(irg);
1971 for (i = 0; i < get_irp_n_irgs(); i++) {
1972 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1974 dump_graph(f, get_irp_irg(i));
1979 /* dump type info */
1980 current_ir_graph = irg;
1981 type_walk_irg(irg, dump_type_info, NULL, f);
1982 inc_irg_visited(get_const_code_irg());
1984 /* dump edges from graph to type info */
1985 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1987 current_ir_graph = rem;
1991 /*---------------------------------------------------------------------*/
1992 /* The following routines dump a control flow graph. */
1993 /*---------------------------------------------------------------------*/
1996 dump_block_to_cfg(ir_node *block, void *env) {
2001 if (is_Block(block)) {
2002 /* This is a block. Dump a node for the block. */
2003 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2004 fprintf (F, "\" label: \"");
2005 if (block == get_irg_start_block(get_irn_irg(block)))
2006 fprintf(F, "Start ");
2007 if (block == get_irg_end_block(get_irn_irg(block)))
2010 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2011 PRINT_NODEID(block);
2013 fprintf(F, "info1:\"");
2014 if (dump_dominator_information_flag)
2015 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2017 /* show arity and possible Bad predecessors of the block */
2018 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2019 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2020 ir_node *pred = get_Block_cfgpred(block, i);
2023 fprintf(F, "Bad pred at pos: ");
2024 fprintf(F, "%d ", i);
2031 fprintf (F, "\""); /* closing quote of info */
2033 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2034 (block == get_irg_end_block(get_irn_irg(block))) )
2035 fprintf(F, " color:blue ");
2037 fprintf(F, " color:yellow ");
2040 /* Dump the edges */
2041 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2042 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2043 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2044 fprintf (F, "edge: { sourcename: \"");
2045 PRINT_NODEID(block);
2046 fprintf (F, "\" targetname: \"");
2048 fprintf (F, "\"}\n");
2051 /* Dump dominator edge */
2052 if (dump_dominator_information_flag && get_Block_idom(block)) {
2053 pred = get_Block_idom(block);
2054 fprintf (F, "edge: { sourcename: \"");
2055 PRINT_NODEID(block);
2056 fprintf (F, "\" targetname: \"");
2058 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2064 dump_cfg (ir_graph *irg, const char *suffix)
2067 ir_graph *rem = current_ir_graph;
2068 int ddif = dump_dominator_information_flag;
2069 int ipv = interprocedural_view;
2071 /* if a filter is set, dump only the irg's that match the filter */
2072 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2075 current_ir_graph = irg;
2077 f = vcg_open(irg, suffix, "-cfg");
2078 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2080 if (interprocedural_view) {
2081 printf("Warning: dumping cfg not in interprocedural view!\n");
2082 interprocedural_view = 0;
2085 if (get_irg_dom_state(irg) != dom_consistent)
2086 dump_dominator_information_flag = 0;
2088 /* walk over the blocks in the graph */
2089 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2090 dump_node(f, get_irg_bad(irg));
2092 dump_dominator_information_flag = ddif;
2093 interprocedural_view = ipv;
2095 current_ir_graph = rem;
2098 static int weight_overall(int rec, int loop) {
2099 return 2*rec + loop;
2102 static int compute_color (int my, int max) {
2107 /* if small, scale to the full color range. */
2109 my = my * (n_colors/max);
2111 int step = 1 + (max / n_colors);
2115 return base_color + n_colors - color;
2118 static int get_entity_color(entity *ent) {
2119 assert(get_entity_irg(ent));
2120 ir_graph *irg = get_entity_irg(ent);
2122 int rec_depth = get_irg_recursion_depth(irg);
2123 int loop_depth = get_irg_loop_depth(irg);
2124 int overall_depth = weight_overall(rec_depth, loop_depth);
2126 int max_rec_depth = irp->max_callgraph_recursion_depth;
2127 int max_loop_depth = irp->max_callgraph_loop_depth;
2128 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2130 int my_rec_color = compute_color(rec_depth, max_rec_depth);
2131 int my_loop_color = compute_color(loop_depth, max_loop_depth);
2132 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2134 return my_overall_color;
2137 void dump_callgraph(const char *suffix) {
2139 int i, n_irgs = get_irp_n_irgs();
2140 int rem = edge_label;
2142 //ident *prefix = new_id_from_str("java/");
2144 F = vcg_open_name("Callgraph", suffix);
2145 dump_vcg_header(F, "Callgraph", NULL);
2147 for (i = 0; i < n_irgs; ++i) {
2148 ir_graph *irg = get_irp_irg(i);
2149 entity *ent = get_irg_entity(irg);
2150 int j, n_callees = get_irg_n_callees(irg);
2152 /* Do not dump runtime system. */
2153 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2155 dump_entity_node(F, ent, get_entity_color(ent));
2156 for (j = 0; j < n_callees; ++j) {
2157 entity *c = get_irg_entity(get_irg_callee(irg, j));
2158 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2159 int be = is_irg_callee_backedge(irg, j);
2162 "label:\"recursion %d\" color: %d" :
2163 "label:\"calls %d\" color: %d";
2164 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2172 /* Dump all irgs in interprocedural view to a single file. */
2173 void dump_all_cg_block_graph(const char *suffix) {
2176 int rem_view = interprocedural_view;
2177 interprocedural_view = 1;
2179 f = vcg_open_name("All_graphs", suffix);
2180 dump_vcg_header(f, "All_graphs", NULL);
2182 /* collect nodes in all irgs reachable in call graph*/
2183 for (i = 0; i < get_irp_n_irgs(); i++)
2184 ird_set_irg_link(get_irp_irg(i), NULL);
2186 cg_walk(clear_link, collect_node, NULL);
2188 /* dump all graphs */
2189 for (i = 0; i < get_irp_n_irgs(); i++) {
2190 current_ir_graph = get_irp_irg(i);
2191 assert(ird_get_irg_link(current_ir_graph));
2192 dump_graph(f, current_ir_graph);
2193 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2197 interprocedural_view = rem_view;
2200 /***********************************************************************/
2201 /* the following routines dumps type information without any ir nodes. */
2202 /***********************************************************************/
2205 dump_type_graph (ir_graph *irg, const char *suffix)
2209 rem = current_ir_graph;
2211 /* if a filter is set, dump only the irg's that match the filter */
2212 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2214 current_ir_graph = irg;
2216 f = vcg_open(irg, suffix, "-type");
2217 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2219 /* walk over the blocks in the graph */
2220 type_walk_irg(irg, dump_type_info, NULL, f);
2221 /* The walker for the const code can be called several times for the
2222 same (sub) experssion. So that no nodes are dumped several times
2223 we decrease the visited flag of the corresponding graph after each
2224 walk. So now increase it finally. */
2225 inc_irg_visited(get_const_code_irg());
2228 current_ir_graph = rem;
2232 dump_all_types (const char *suffix)
2234 FILE *f = vcg_open_name("All_types", suffix);
2235 dump_vcg_header(f, "All_types", NULL);
2236 type_walk(dump_type_info, NULL, f);
2237 inc_irg_visited(get_const_code_irg());
2242 dump_class_hierarchy (bool entities, const char *suffix)
2244 FILE *f = vcg_open_name("class_hierarchy", suffix);
2248 dump_vcg_header(f, "class_hierarchy", NULL);
2253 type_walk(dump_class_hierarchy_node, NULL, &env);
2257 /***********************************************************************/
2258 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2260 /* dump_ir_block_graph */
2262 /* dump_type_graph */
2263 /* dump_ir_graph_w_types */
2264 /***********************************************************************/
2266 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2268 for (i=0; i < get_irp_n_irgs(); i++) {
2269 dmp_grph(get_irp_irg(i), suffix);
2274 /**********************************************************************************
2275 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2276 * packed together in one subgraph/box *
2277 **********************************************************************************/
2279 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2280 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2282 ir_loop *son = NULL;
2284 /* Dump a new loop node. */
2285 dump_loop_node(F, loop);
2287 /* Dump the loop elements. */
2289 for(i = 0; i < get_loop_n_elements(loop); i++) {
2290 le = get_loop_element(loop, i);
2292 if (get_kind(son) == k_ir_loop) {
2294 /* We are a loop son -> Recurse */
2296 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2297 fprintf(F, "\" }\n");
2298 fprintf (F, "edge: {sourcename: \"");
2300 fprintf (F, "\" targetname: \"");
2302 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2303 loop_node_started = 0;
2305 dump_loop_son_edge(F, loop, son_number++);
2306 dump_loops_standalone(F, son);
2307 } else if (get_kind(son) == k_ir_node) {
2308 /* We are a loop node -> Collect firm nodes */
2310 ir_node *n = le.node;
2313 if (!loop_node_started) {
2314 /* Start a new node which contains all firm nodes of the current loop */
2315 fprintf (F, "node: { title: \"");
2317 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2318 loop_node_started = 1;
2324 bad |= dump_node_opcode(F, n);
2325 bad |= dump_node_mode(F, n);
2326 bad |= dump_node_typeinfo(F, n);
2328 bad |= dump_node_nodeattr(F, n);
2329 fprintf (F, " %ld", get_irn_node_nr(n));
2330 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2331 } else { /* for callgraph loop tree */
2332 assert(get_kind(son) == k_ir_graph);
2333 /* We are a loop node -> Collect firm graphs */
2334 ir_graph *n = (ir_graph *)le.node;
2335 if (!loop_node_started) {
2336 /* Start a new node which contains all firm nodes of the current loop */
2337 fprintf (F, "node: { title: \"");
2339 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2340 loop_node_started = 1;
2345 fprintf (F, " %s", get_irg_dump_name(n));
2346 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2350 if (loop_node_started) {
2351 fprintf(F, "\" }\n");
2352 fprintf (F, "edge: {sourcename: \"");
2354 fprintf (F, "\" targetname: \"");
2356 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2357 loop_node_started = 0;
2361 void dump_loop_tree(ir_graph *irg, const char *suffix)
2364 ir_graph *rem = current_ir_graph;
2365 int el_rem = edge_label;
2368 /* if a filter is set, dump only the irg's that match the filter */
2369 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2372 current_ir_graph = irg;
2374 f = vcg_open(irg, suffix, "-looptree");
2375 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2377 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2381 edge_label = el_rem;
2382 current_ir_graph = rem;
2385 void dump_callgraph_loop_tree(const char *suffix) {
2387 F = vcg_open_name("Callgraph_looptree", suffix);
2388 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2389 dump_loops_standalone(F, irp->outermost_cg_loop);
2394 /*******************************************************************************/
2395 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2396 /*******************************************************************************/
2398 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2399 int i, son_number = 0, node_number = 0;
2401 if (dump_loop_information_flag) dump_loop_node(F, loop);
2403 for (i = 0; i < get_loop_n_elements(loop); i++) {
2404 loop_element le = get_loop_element(loop, i);
2405 if (*(le.kind) == k_ir_loop) {
2406 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2408 collect_nodeloop(F, le.son, loopnodes);
2410 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2411 eset_insert(loopnodes, le.node);
2416 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2419 for(i = 0; i < get_loop_n_elements(loop); i++) {
2420 loop_element le = get_loop_element(loop, i);
2421 if (*(le.kind) == k_ir_loop) {
2423 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2425 if (is_Block(le.node)) start = 0; else start = -1;
2426 for (j = start; j < get_irn_arity(le.node); j++) {
2427 ir_node *pred = get_irn_n(le.node, j);
2428 if (!eset_contains(loopnodes, pred)) {
2429 eset_insert(extnodes, pred);
2430 if (!is_Block(pred)) {
2431 pred = get_nodes_block(pred);
2432 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2440 void dump_loop(ir_loop *l, const char *suffix) {
2443 eset *loopnodes = eset_create();
2444 eset *extnodes = eset_create();
2447 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2448 F = vcg_open_name (name, suffix);
2449 dump_vcg_header(F, name, NULL);
2451 /* collect all nodes to dump */
2452 collect_nodeloop(F, l, loopnodes);
2453 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2455 /* build block lists */
2456 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2457 set_irn_link(n, NULL);
2458 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2459 set_irn_link(n, NULL);
2460 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2462 b = get_nodes_block(n);
2463 set_irn_link(n, get_irn_link(b));
2466 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2468 b = get_nodes_block(n);
2469 set_irn_link(n, get_irn_link(b));
2473 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2475 fprintf(F, "graph: { title: \"");
2477 fprintf(F, "\" label: \"");
2478 dump_node_opcode(F, b);
2479 fprintf (F, " %ld", get_irn_node_nr(b));
2480 fprintf(F, "\" status:clustered color:yellow\n");
2482 /* dump the blocks edges */
2483 dump_ir_data_edges(F, b);
2485 /* dump the nodes that go into the block */
2486 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2487 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2489 overrule_nodecolor = NULL;
2490 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2493 /* Close the vcg information for the block */
2495 dump_const_node_local(F, b);
2498 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2500 fprintf(F, "graph: { title: \"");
2502 fprintf(F, "\" label: \"");
2503 dump_node_opcode(F, b);
2504 fprintf (F, " %ld", get_irn_node_nr(b));
2505 fprintf(F, "\" status:clustered color:lightblue\n");
2507 /* dump the nodes that go into the block */
2508 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2509 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2511 overrule_nodecolor = NULL;
2512 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2515 /* Close the vcg information for the block */
2517 dump_const_node_local(F, b);
2521 eset_destroy(loopnodes);
2522 eset_destroy(extnodes);