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));
522 fprintf (F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
527 fprintf (F, "%s", get_irn_opname(n));
535 dump_node_mode(FILE *F, ir_node *n)
539 switch (get_irn_opcode(n)) {
558 fprintf(F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
566 static int dump_node_typeinfo(FILE *F, ir_node *n) {
569 if (opt_dump_analysed_type_info) {
570 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
571 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
572 type *tp = get_irn_type(n);
574 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
583 dump_node_nodeattr(FILE *F, ir_node *n)
587 switch (get_irn_opcode(n)) {
589 if (false && interprocedural_view) {
590 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
594 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
595 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
597 fprintf (F, "%ld", get_Proj_proj(n));
601 fprintf (F, "%ld", get_Filter_proj(n));
604 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
607 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
610 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
620 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
623 fprintf(F, "color: red");
626 switch (get_irn_opcode(n)) {
633 fprintf (F, "color: blue");
636 fprintf (F, "color: lightyellow");
639 fprintf (F, "color: green");
645 fprintf (F, "color: yellow");
648 PRINT_DEFAULT_NODE_ATTR;
651 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
654 static INLINE int dump_node_info(FILE *F, ir_node *n)
660 fprintf (F, " info1: \"");
661 if (opt_dump_pointer_values_to_info)
662 fprintf (F, "addr: %p \n", (void *)n);
663 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
664 fprintf (F, "visited: %ld \n", get_irn_visited(n));
665 irg = get_irn_irg(n);
666 if (irg != get_const_code_irg())
667 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
669 if (get_op_pinned(get_irn_op(n)) == op_pin_state_floats &&
670 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
671 fprintf(F, "node was pinned in ");
672 dump_node_opcode(F, get_nodes_block(n));
673 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
677 /* show all predecessor nodes */
678 fprintf(F, "pred nodes: \n");
681 dump_node_opcode(F, get_nodes_block(n));
682 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
684 for ( i = 0; i < get_irn_arity(n); ++i) {
685 fprintf(F, " %d: ", i);
686 dump_node_opcode(F, get_irn_n(n, i));
687 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
691 fprintf(F, "arity: %d", get_irn_arity(n));
692 if ((get_irn_op(n) == op_Block) ||
693 (get_irn_op(n) == op_Phi) ||
694 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
695 fprintf(F, " backedges:");
697 for (i = 0; i < get_irn_arity(n); i++)
698 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
702 /* Loop node Someone else please tell me what's wrong ...
703 if (get_irn_loop(n)) {
704 ir_loop *loop = get_irn_loop(n);
706 fprintf(F, " in loop %d with depth %d\n",
707 get_loop_loop_nr(loop), get_loop_depth(loop));
712 switch (get_irn_opcode(n)) {
714 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
715 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
716 for (i = 0; i < get_method_n_params(tp); ++i)
717 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
720 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
723 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
726 entity *ent = get_Sel_entity(n);
729 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
730 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
733 fprintf(F, "<NULL entity>\n");
738 type *tp = get_Call_type(n);
739 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
740 for (i = 0; i < get_method_n_params(tp); ++i)
741 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
742 for (i = 0; i < get_method_n_ress(tp); ++i)
743 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
744 if (0 && Call_has_callees(n)) {
745 fprintf(F, "possible callees: \n");
746 for (i = 0; i < get_Call_n_callees(n); i++) {
747 if (!get_Call_callee(n, i)) {
748 fprintf(F, " %d external method\n", i);
750 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
755 case iro_CallBegin: {
756 ir_node *call = get_CallBegin_call(n);
757 if (Call_has_callees(call)) {
758 fprintf(F, "possible callees: \n");
759 for (i = 0; i < get_Call_n_callees(call); i++) {
760 if (!get_Call_callee(call, i)) {
761 fprintf(F, " %d external method\n", i);
763 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
769 if (!interprocedural_view) {
770 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
771 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
772 for (i = 0; i < get_method_n_ress(tp); ++i)
773 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
777 type *tp = get_Const_type(n);
778 assert(tp != none_type);
779 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
782 switch(get_SymConst_kind(n)) {
783 case symconst_addr_name:
784 fprintf(F, "kind addr_name\n");
786 case symconst_addr_ent:
787 fprintf(F, "kind addr_ent\n");
789 case symconst_type_tag:
790 fprintf(F, "kind type_tag\n");
793 fprintf(F, "kind size\n");
799 if (interprocedural_view) {
800 fprintf(F, "intra predecessor nodes:\n");
801 for (i = 0; i < get_irn_intra_arity(n); i++) {
802 ir_node *pred = get_irn_intra_n(n, i);
803 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
806 fprintf(F, "inter predecessor nodes:\n");
807 for (i = 0; i < get_irn_inter_arity(n); i++) {
808 ir_node *pred = get_irn_inter_n(n, i);
809 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
810 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
815 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
818 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
824 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
825 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
826 if (get_irn_type(n) != none_type)
827 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
836 bool is_constlike_node(ir_node *n) {
837 ir_op *op = get_irn_op(n);
838 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
842 /* outputs the predecessors of n, that are constants, local. I.e.,
843 generates a copy of the constant predecessors for each node called with. */
844 static void dump_const_node_local(FILE *F, ir_node *n) {
846 if (!get_opt_dump_const_local()) return;
848 /* Use visited flag to avoid outputting nodes twice.
849 initialize it first. */
850 for (i = 0; i < get_irn_arity(n); i++) {
851 ir_node *con = get_irn_n(n, i);
852 if (is_constlike_node(con)) {
853 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
857 for (i = 0; i < get_irn_arity(n); i++) {
858 ir_node *con = get_irn_n(n, i);
859 if (is_constlike_node(con) && irn_not_visited(con)) {
862 mark_irn_visited(con);
863 /* Generate a new name for the node by appending the names of
865 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
866 fprintf(F, " label: \"");
867 bad |= dump_node_opcode(F, con);
868 bad |= dump_node_mode(F, con);
869 bad |= dump_node_typeinfo(F, con);
871 bad |= dump_node_nodeattr(F, con);
872 fprintf(F, " %ld", get_irn_node_nr(con));
874 bad |= dump_node_info(F, con);
875 dump_node_vcgattr(F, con, bad);
881 static void INLINE print_node_error(FILE *F, const char *p)
886 fprintf (F, " info2: \"%s\"", p);
889 static void dump_node(FILE *F, ir_node *n)
894 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
896 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
898 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
899 bad |= dump_node_opcode(F, n);
900 bad |= dump_node_mode(F, n);
901 bad |= dump_node_typeinfo(F, n);
903 bad |= dump_node_nodeattr(F, n);
904 fprintf(F, " %ld", get_irn_node_nr(n));
906 bad |= dump_node_info(F, n);
907 print_node_error(F, p);
908 dump_node_vcgattr(F, n, bad);
910 dump_const_node_local(F, n);
917 /* dump the edge to the block this node belongs to */
919 dump_ir_block_edge(FILE *F, ir_node *n) {
920 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
921 if (is_no_Block(n)) {
922 ir_node *block = get_nodes_block(n);
924 fprintf (F, "edge: { sourcename: \"");
926 fprintf (F, "\" targetname: ");
927 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
928 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
933 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
934 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
935 fprintf (F, INTRA_DATA_EDGE_ATTR);
937 fprintf (F, INTER_DATA_EDGE_ATTR);
941 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
942 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
943 fprintf (F, INTRA_MEM_EDGE_ATTR);
945 fprintf (F, INTER_MEM_EDGE_ATTR);
949 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
952 if (dump_backedge_information_flag && is_backedge(from, to))
953 fprintf (F, BACK_EDGE_ATTR);
955 switch (get_irn_opcode(from)) {
957 fprintf (F, CF_EDGE_ATTR);
959 case iro_Start: break;
962 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
963 fprintf (F, CF_EDGE_ATTR);
964 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
965 fprintf (F, INTER_MEM_EDGE_ATTR);
973 print_data_edge_vcgattr(F, from, to);
978 print_mem_edge_vcgattr(F, from, to);
980 print_data_edge_vcgattr(F, from, to);
984 print_data_edge_vcgattr(F, from, to);
989 print_mem_edge_vcgattr(F, from, to);
991 print_data_edge_vcgattr(F, from, to);
998 print_data_edge_vcgattr(F, from, to);
1005 print_mem_edge_vcgattr(F, from, to);
1007 print_data_edge_vcgattr(F, from, to);
1019 print_data_edge_vcgattr(F, from, to);
1022 if (get_irn_modecode(from) == irm_M)
1023 fprintf (F, INTER_MEM_EDGE_ATTR);
1025 print_data_edge_vcgattr(F, from, to);
1032 print_mem_edge_vcgattr(F, from, to);
1034 print_data_edge_vcgattr(F, from, to);
1037 print_mem_edge_vcgattr(F, from, to);
1039 case iro_Tuple: break;
1042 switch (get_irn_modecode(from)) {
1044 fprintf (F, CF_EDGE_ATTR);
1047 fprintf (F, INTER_MEM_EDGE_ATTR);
1050 print_data_edge_vcgattr(F, from, to);
1054 case iro_Bad: break;
1055 case iro_Unknown: break;
1057 switch (get_irn_modecode(from)) {
1059 fprintf (F, INTRA_MEM_EDGE_ATTR);
1062 fprintf (F, CF_EDGE_ATTR);
1065 print_data_edge_vcgattr(F, from, to);
1073 /* dump edges to our inputs */
1075 dump_ir_data_edges(FILE *F, ir_node *n) {
1076 int i, visited = get_irn_visited(n);
1078 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1081 for (i = 0; i < get_irn_arity(n); i++) {
1082 ir_node * pred = get_irn_n(n, i);
1085 if ((interprocedural_view && get_irn_visited(pred) < visited))
1086 continue; /* pred not dumped */
1088 if (dump_backedge_information_flag && is_backedge(n, i))
1089 fprintf (F, "backedge: {sourcename: \"");
1091 fprintf (F, "edge: {sourcename: \"");
1093 fprintf (F, "\" targetname: ");
1094 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1095 PRINT_CONSTID(n, pred);
1097 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1099 fprintf (F, " label: \"%d\" ", i);
1100 print_edge_vcgattr(F, n, i);
1105 /** Dumps a node and its edges but not the block edge
1108 dump_node_wo_blockedge (ir_node *n, void *env) {
1111 dump_ir_data_edges(F, n);
1114 /** Dumps a node and its edges.
1117 dump_whole_node (ir_node *n, void *env) {
1119 dump_node_wo_blockedge(n, env);
1120 if (!node_floats(n)) dump_ir_block_edge(F, n);
1124 dump_const_node(ir_node *n, void *env) {
1125 if (is_Block(n)) return;
1126 dump_node_wo_blockedge(n, env);
1129 /***********************************************************************/
1130 /* the following routines dump the nodes/irgs bracketed to graphs. */
1131 /***********************************************************************/
1133 /** Dumps a constant expression as entity initializer, array bound ...
1135 static void dump_const_expression(FILE *F, ir_node *value) {
1136 ir_graph *rem = current_ir_graph;
1137 int rem_dump_const_local = dump_const_local;
1138 dump_const_local = 0;
1139 current_ir_graph = get_const_code_irg();
1140 irg_walk(value, dump_const_node, NULL, F);
1141 /* Decrease visited flag so that we walk with the same flag for the next
1142 expresssion. This guarantees that we don't dump the same node twice,
1143 as for const expressions cse is performed to save memory. */
1144 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1145 current_ir_graph = rem;
1146 dump_const_local = rem_dump_const_local;
1149 /** Dump a block as graph containing its nodes.
1151 * Expects to find nodes belonging to the block as list in its
1153 * Dumps the edges of all nodes including itself. */
1155 dump_whole_block(FILE *F, ir_node *block) {
1157 assert(is_Block(block));
1159 fprintf(F, "graph: { title: \"");
1160 PRINT_NODEID(block);
1161 fprintf(F, "\" label: \"");
1162 dump_node_opcode(F, block);
1163 fprintf (F, " %ld", get_irn_node_nr(block));
1165 if (get_opt_dump_abstvals())
1166 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1168 fprintf(F, "\" status:clustered color:%s \n",
1169 get_Block_matured(block) ? "yellow" : "red");
1171 /* dump the blocks edges */
1172 dump_ir_data_edges(F, block);
1174 /* dump the nodes that go into the block */
1175 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1177 dump_ir_data_edges(F, node);
1180 /* Close the vcg information for the block */
1182 dump_const_node_local(F, block);
1184 dump_chi_term(F, block);
1189 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1190 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1192 dump_block_graph(FILE *F, ir_graph *irg) {
1194 ir_graph *rem = current_ir_graph;
1195 ir_node **arr = ird_get_irg_link(irg);
1196 current_ir_graph = irg;
1198 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1199 ir_node * node = arr[i];
1200 if (is_Block(node)) {
1201 /* Dumps the block and all the nodes in the block, which are to
1202 be found in Block->link. */
1203 dump_whole_block(F, node);
1205 /* Nodes that are not in a Block. */
1207 dump_ir_data_edges(F, node);
1211 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1212 dump_loop_nodes_into_graph(F, irg);
1214 current_ir_graph = rem;
1217 /** Dumps an irg as a graph.
1218 * If interprocedural view edges can point to nodes out of this graph.
1220 static void dump_graph(FILE *F, ir_graph *irg) {
1222 fprintf(F, "graph: { title: \"");
1224 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1225 get_ent_dump_name(get_irg_entity(irg)));
1227 dump_block_graph(F, irg);
1229 /* Close the vcg information for the irg */
1230 fprintf(F, "}\n\n");
1233 /*******************************************************************/
1234 /* Basic type and entity nodes and edges. */
1235 /*******************************************************************/
1237 /* dumps the edges between nodes and their type or entity attributes. */
1238 static void dump_node2type_edges(ir_node *n, void *env)
1243 switch (get_irn_opcode(n)) {
1245 /* @@@ some consts have an entity */
1248 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1249 || (get_SymConst_kind(n) ==symconst_size))
1251 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1255 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1258 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1261 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1264 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1267 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1275 static int print_type_info(FILE *F, type *tp) {
1278 if (get_type_state(tp) == layout_undefined) {
1279 fprintf(F, "state: layout_undefined\n");
1281 fprintf(F, "state: layout_fixed,\n");
1283 if (get_type_mode(tp))
1284 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1285 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1290 static void print_typespecific_info(FILE *F, type *tp) {
1291 switch (get_type_tpop_code(tp)) {
1294 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1301 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1302 fprintf(F, "params: %d\n", get_method_n_params(tp));
1303 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1311 case tpo_enumeration:
1325 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1326 switch (get_type_tpop_code(tp)) {
1329 if (peculiarity_existent == get_class_peculiarity(tp))
1330 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1332 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1336 fprintf (F, " " TYPE_METH_NODE_ATTR);
1347 case tpo_enumeration:
1360 static int print_type_node(FILE *F, type *tp)
1364 fprintf (F, "node: {title: ");
1366 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1367 fprintf (F, " info1: \"");
1368 bad |= print_type_info(F, tp);
1369 print_typespecific_info(F, tp);
1371 print_typespecific_vcgattr(F, tp);
1377 #define X(a) case a: fprintf(F, #a); break
1378 void dump_entity_node(FILE *F, entity *ent, int color)
1380 fprintf (F, "node: {title: \"");
1381 PRINT_ENTID(ent); fprintf(F, "\"");
1382 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1383 fprintf (F, "label: ");
1384 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1386 fprintf(F, "color: %d", color);
1388 fprintf (F, ENTITY_NODE_ATTR);
1389 fprintf (F, "\n info1: \"");
1391 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1393 fprintf(F, "\"\n}\n");
1397 static void dump_enum_item(FILE *F, type *tp, int pos)
1400 ident *id = get_enumeration_nameid(tp, pos);
1401 tarval *tv = get_enumeration_enum(tp, pos);
1403 tarval_snprintf(buf, sizeof(buf), tv);
1404 fprintf (F, "node: {title: \"");
1405 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1406 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1407 fprintf (F, "label: ");
1408 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1409 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1412 /* dumps a type or entity and it's edges. */
1414 dump_type_info(type_or_ent *tore, void *env) {
1416 int i = 0; /* to shutup gcc */
1418 /* dump this type or entity */
1420 switch (get_kind(tore)) {
1423 entity *ent = (entity *)tore;
1426 dump_entity_node(F, ent, 0);
1428 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1429 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1430 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1431 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1432 if(is_class_type(get_entity_owner(ent))) {
1433 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1434 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1436 /* attached subgraphs */
1437 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1438 if (is_atomic_entity(ent)) {
1439 value = get_atomic_ent_value(ent);
1441 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1442 /* DDMN(value); $$$ */
1443 dump_const_expression(F, value);
1446 if (is_compound_entity(ent)) {
1447 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1448 value = get_compound_ent_value(ent, i);
1450 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1451 dump_const_expression(F, value);
1452 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1454 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1455 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1456 get_compound_ent_value_member(ent, i), i);
1465 type *tp = (type *)tore;
1466 print_type_node(F, tp);
1467 /* and now the edges */
1468 switch (get_type_tpop_code(tp)) {
1471 for (i=0; i < get_class_n_supertypes(tp); i++)
1472 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1473 for (i=0; i < get_class_n_members(tp); i++)
1474 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1478 for (i=0; i < get_struct_n_members(tp); i++)
1479 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1483 for (i = 0; i < get_method_n_params(tp); i++)
1484 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1485 for (i = 0; i < get_method_n_ress(tp); i++)
1486 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1490 for (i = 0; i < get_union_n_members(tp); i++)
1491 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1495 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1496 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1497 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1498 ir_node *upper = get_array_upper_bound(tp, i);
1499 ir_node *lower = get_array_lower_bound(tp, i);
1500 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1501 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1502 dump_const_expression(F, upper);
1503 dump_const_expression(F, lower);
1507 case tpo_enumeration:
1509 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1510 dump_enum_item(F, tp, i);
1511 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1516 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1524 break; /* case k_type */
1527 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1529 } /* switch kind_or_entity */
1532 typedef struct _h_env {
1537 /** For dumping class hierarchies.
1538 * Dumps a class type node and a superclass edge.
1539 * If env->dump_ent dumps entities of classes and overwrites edges.
1542 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1545 int i = 0; /* to shutup gcc */
1547 /* dump this type or entity */
1548 switch (get_kind(tore)) {
1550 entity *ent = (entity *)tore;
1551 if (get_entity_owner(ent) == get_glob_type()) break;
1552 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1553 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1555 dump_entity_node(F, ent, 0);
1557 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1558 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1559 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1561 } break; /* case k_entity */
1564 type *tp = (type *)tore;
1565 if (tp == get_glob_type()) break;
1566 switch (get_type_tpop_code(tp)) {
1568 print_type_node(F, tp);
1569 /* and now the edges */
1570 for (i=0; i < get_class_n_supertypes(tp); i++)
1572 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1578 break; /* case k_type */
1581 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1583 } /* switch kind_or_entity */
1586 /*******************************************************************/
1587 /* dump analysis information that is expressed in graph terms. */
1588 /*******************************************************************/
1590 /* dump out edges */
1592 dump_out_edge(ir_node *n, void *env) {
1595 for (i = 0; i < get_irn_n_outs(n); i++) {
1596 assert(get_irn_out(n, i));
1597 fprintf (F, "edge: {sourcename: \"");
1599 fprintf (F, "\" targetname: \"");
1600 PRINT_NODEID(get_irn_out(n, i));
1601 fprintf (F, "\" color: red linestyle: dashed");
1607 dump_loop_label(FILE *F, ir_loop *loop) {
1608 fprintf (F, "loop %d, %d sons, %d nodes",
1609 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1612 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1613 fprintf (F, " info1: \"");
1614 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1615 #if DEBUG_libfirm /* GL @@@ debug analyses */
1616 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1622 dump_loop_node(FILE *F, ir_loop *loop) {
1623 fprintf (F, "node: {title: \"");
1625 fprintf (F, "\" label: \"");
1626 dump_loop_label(F, loop);
1628 dump_loop_info(F, loop);
1634 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1636 fprintf (F, "edge: {sourcename: \"");
1638 fprintf (F, "\" targetname: \"");
1639 PRINT_NODEID(get_loop_node(loop, i));
1640 fprintf (F, "\" color: green");
1645 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1647 fprintf (F, "edge: {sourcename: \"");
1649 fprintf (F, "\" targetname: \"");
1650 PRINT_LOOPID(get_loop_son(loop, i));
1651 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1652 get_loop_element_pos(loop, get_loop_son(loop, i)));
1656 void dump_loops(FILE *F, ir_loop *loop) {
1658 /* dump this loop node */
1659 dump_loop_node(F, loop);
1661 /* dump edges to nodes in loop -- only if it is a real loop */
1662 if (get_loop_depth(loop) != 0) {
1663 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1664 dump_loop_node_edge(F, loop, i);
1667 for (i = 0; i < get_loop_n_sons(loop); i++) {
1668 dump_loops(F, get_loop_son(loop, i));
1669 dump_loop_son_edge(F, loop, i);
1674 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1675 ir_graph *rem = current_ir_graph;
1676 current_ir_graph = irg;
1678 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1680 current_ir_graph = rem;
1685 * dumps the VCG header
1688 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1697 if (!orientation) orientation = "bottom_to_top";
1701 "graph: { title: \"ir graph of %s\"\n"
1702 "display_edge_labels: %s\n"
1703 "layoutalgorithm: mindepth\n"
1704 "manhattan_edges: yes\n"
1705 "port_sharing: no\n"
1707 "classname 1: \"intrablock Data\"\n"
1708 "classname 16: \"interblock Data\"\n"
1709 "classname 2: \"Block\"\n"
1710 "classname 13: \"Control Flow\"\n"
1711 "classname 14: \"intrablock Memory\"\n"
1712 "classname 17: \"interblock Memory\"\n"
1713 "classname 15: \"Dominators\"\n"
1714 "classname 3: \"Entity type\"\n"
1715 "classname 4: \"Entity owner\"\n"
1716 "classname 5: \"Method Param\"\n"
1717 "classname 6: \"Method Res\"\n"
1718 "classname 7: \"Super\"\n"
1719 "classname 8: \"Union\"\n"
1720 "classname 9: \"Points-to\"\n"
1721 "classname 10: \"Array Element Type\"\n"
1722 "classname 11: \"Overwrites\"\n"
1723 "classname 12: \"Member\"\n"
1724 "infoname 1: \"Attribute\"\n"
1725 "infoname 2: \"Verification errors\"\n",
1726 name, label, orientation);
1728 /* don't use all, the range is too whith/black. */
1732 "colorentry 100: 0 0 0\n"
1733 "colorentry 101: 20 0 0\n"
1734 "colorentry 102: 40 0 0\n"
1735 "colorentry 103: 60 0 0\n"
1736 "colorentry 104: 80 0 0\n"
1737 "colorentry 105: 100 0 0\n"
1738 "colorentry 106: 120 0 0\n"
1739 "colorentry 107: 140 0 0\n"
1740 "colorentry 108: 150 0 0\n"
1741 "colorentry 109: 180 0 0\n"
1742 "colorentry 110: 200 0 0\n"
1743 "colorentry 111: 220 0 0\n"
1744 "colorentry 112: 240 0 0\n"
1745 "colorentry 113: 255 0 0\n"
1746 "colorentry 113: 255 20 20\n"
1747 "colorentry 114: 255 40 40\n"
1748 "colorentry 115: 255 60 60\n"
1749 "colorentry 116: 255 80 80\n"
1750 "colorentry 117: 255 100 100\n"
1751 "colorentry 118: 255 120 120\n"
1752 "colorentry 119: 255 140 140\n"
1753 "colorentry 120: 255 150 150\n"
1754 "colorentry 121: 255 180 180\n"
1755 "colorentry 122: 255 200 200\n"
1756 "colorentry 123: 255 220 220\n"
1757 "colorentry 124: 255 240 240\n"
1758 "colorentry 125: 255 250 250\n"
1761 fprintf (F, "\n"); /* a separator */
1767 * @param irg The graph to be dumped
1768 * @param suffix1 first filename suffix
1769 * @param suffix2 second filename suffix
1771 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1773 const char *nm = get_irg_dump_name(irg);
1774 int len = strlen(nm), i, j;
1775 char *fname; /* filename to put the vcg information in */
1777 if (!suffix1) suffix1 = "";
1778 if (!suffix2) suffix2 = "";
1780 /* open file for vcg graph */
1781 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1783 /* strncpy (fname, nm, len); */ /* copy the filename */
1785 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1787 fname[j] = '@'; j++; fname[j] = '1'; j++;
1788 } else if (nm[i] == '@') {
1789 fname[j] = '@'; j++; fname[j] = '2'; j++;
1791 fname[j] = nm[i]; j++;
1795 strcat (fname, suffix1); /* append file suffix */
1796 strcat (fname, suffix2); /* append file suffix */
1797 strcat (fname, ".vcg"); /* append the .vcg suffix */
1798 F = fopen (fname, "w"); /* open file for writing */
1800 panic("cannot open %s for writing (%m)", fname); /* not reached */
1810 * @param irg The graph to be dumped
1811 * @param suffix filename suffix
1813 static FILE *vcg_open_name (const char *name, const char *suffix) {
1815 char *fname; /* filename to put the vcg information in */
1816 int i, j, len = strlen(name);
1818 if (!suffix) suffix = "";
1820 /** open file for vcg graph */
1821 fname = malloc (len * 2 + 5 + strlen(suffix));
1822 /* strcpy (fname, name);*/ /* copy the filename */
1824 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1825 if (name[i] == '/') {
1826 fname[j] = '@'; j++; fname[j] = '1'; j++;
1827 } else if (name[i] == '@') {
1828 fname[j] = '@'; j++; fname[j] = '2'; j++;
1830 fname[j] = name[i]; j++;
1834 strcat (fname, suffix);
1835 strcat (fname, ".vcg"); /* append the .vcg suffix */
1836 F = fopen (fname, "w"); /* open file for writing */
1838 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1846 * Dumps the vcg file footer
1848 static INLINE void dump_vcg_footer (FILE *F) {
1853 * close the vcg file
1856 vcg_close (FILE *F) {
1857 dump_vcg_footer(F); /* print footer */
1858 fclose (F); /* close vcg file */
1861 /************************************************************************/
1862 /************************************************************************/
1863 /* Routines that dump all or parts of the firm representation to a file */
1864 /************************************************************************/
1865 /************************************************************************/
1867 /************************************************************************/
1868 /* Dump ir graphs, differnt formats and additional information. */
1869 /************************************************************************/
1871 /** Routine to dump a graph, blocks as conventional nodes.
1874 dump_ir_graph (ir_graph *irg, const char *suffix )
1879 rem = current_ir_graph;
1881 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1882 current_ir_graph = irg;
1883 if (interprocedural_view) suffix1 = "-pure-ip";
1884 else suffix1 = "-pure";
1885 f = vcg_open(irg, suffix, suffix1);
1886 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1888 /* walk over the graph */
1889 /* dump_whole_node must be called in post visiting predecessors */
1890 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1892 /* dump the out edges in a separate walk */
1893 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1894 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1899 current_ir_graph = rem;
1904 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1910 if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1911 if (interprocedural_view) suffix1 = "-ip";
1913 f = vcg_open(irg, suffix, suffix1);
1914 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1916 construct_block_lists(irg);
1918 for (i = 0; i < get_irp_n_irgs(); i++) {
1919 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1921 dump_graph(f, get_irp_irg(i));
1929 /** dumps a graph with type information
1932 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1935 ir_graph *rem = current_ir_graph;
1938 /* if a filter is set, dump only the irg's that match the filter */
1939 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1942 current_ir_graph = irg;
1944 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1945 else suffix1 = "-pure-wtypes";
1946 f = vcg_open(irg,suffix, suffix1);
1947 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1949 /* dump common ir graph */
1950 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1951 /* dump type info */
1952 type_walk_irg(irg, dump_type_info, NULL, f);
1953 inc_irg_visited(get_const_code_irg());
1954 /* dump edges from graph to type info */
1955 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1958 current_ir_graph = rem;
1962 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1967 ir_graph *rem = current_ir_graph;
1969 /* if a filter is set, dump only the irg's that match the filter */
1970 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1973 if (interprocedural_view) suffix1 = "-wtypes-ip";
1974 else suffix1 = "-wtypes";
1975 f = vcg_open(irg, suffix, suffix1);
1976 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1978 /* dump common blocked ir graph */
1979 construct_block_lists(irg);
1981 for (i = 0; i < get_irp_n_irgs(); i++) {
1982 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1984 dump_graph(f, get_irp_irg(i));
1989 /* dump type info */
1990 current_ir_graph = irg;
1991 type_walk_irg(irg, dump_type_info, NULL, f);
1992 inc_irg_visited(get_const_code_irg());
1994 /* dump edges from graph to type info */
1995 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1997 current_ir_graph = rem;
2001 /*---------------------------------------------------------------------*/
2002 /* The following routines dump a control flow graph. */
2003 /*---------------------------------------------------------------------*/
2006 dump_block_to_cfg(ir_node *block, void *env) {
2011 if (is_Block(block)) {
2012 /* This is a block. Dump a node for the block. */
2013 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2014 fprintf (F, "\" label: \"");
2015 if (block == get_irg_start_block(get_irn_irg(block)))
2016 fprintf(F, "Start ");
2017 if (block == get_irg_end_block(get_irn_irg(block)))
2020 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2021 PRINT_NODEID(block);
2023 fprintf(F, "info1:\"");
2024 if (dump_dominator_information_flag)
2025 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2027 /* show arity and possible Bad predecessors of the block */
2028 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2029 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2030 ir_node *pred = get_Block_cfgpred(block, i);
2033 fprintf(F, "Bad pred at pos: ");
2034 fprintf(F, "%d ", i);
2041 fprintf (F, "\""); /* closing quote of info */
2043 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2044 (block == get_irg_end_block(get_irn_irg(block))) )
2045 fprintf(F, " color:blue ");
2047 fprintf(F, " color:yellow ");
2050 /* Dump the edges */
2051 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2052 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2053 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2054 fprintf (F, "edge: { sourcename: \"");
2055 PRINT_NODEID(block);
2056 fprintf (F, "\" targetname: \"");
2058 fprintf (F, "\"}\n");
2061 /* Dump dominator edge */
2062 if (dump_dominator_information_flag && get_Block_idom(block)) {
2063 pred = get_Block_idom(block);
2064 fprintf (F, "edge: { sourcename: \"");
2065 PRINT_NODEID(block);
2066 fprintf (F, "\" targetname: \"");
2068 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2074 dump_cfg (ir_graph *irg, const char *suffix)
2077 ir_graph *rem = current_ir_graph;
2078 int ddif = dump_dominator_information_flag;
2079 int ipv = interprocedural_view;
2081 /* if a filter is set, dump only the irg's that match the filter */
2082 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2085 current_ir_graph = irg;
2087 f = vcg_open(irg, suffix, "-cfg");
2088 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2090 if (interprocedural_view) {
2091 printf("Warning: dumping cfg not in interprocedural view!\n");
2092 interprocedural_view = 0;
2095 if (get_irg_dom_state(irg) != dom_consistent)
2096 dump_dominator_information_flag = 0;
2098 /* walk over the blocks in the graph */
2099 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2100 dump_node(f, get_irg_bad(irg));
2102 dump_dominator_information_flag = ddif;
2103 interprocedural_view = ipv;
2105 current_ir_graph = rem;
2108 static int weight_overall(int rec, int loop) {
2109 return 2*rec + loop;
2112 static int compute_color (int my, int max) {
2117 /* if small, scale to the full color range. */
2119 my = my * (n_colors/max);
2121 int step = 1 + (max / n_colors);
2125 return base_color + n_colors - color;
2128 static int get_entity_color(entity *ent) {
2129 assert(get_entity_irg(ent));
2130 ir_graph *irg = get_entity_irg(ent);
2132 int rec_depth = get_irg_recursion_depth(irg);
2133 int loop_depth = get_irg_loop_depth(irg);
2134 int overall_depth = weight_overall(rec_depth, loop_depth);
2136 int max_rec_depth = irp->max_callgraph_recursion_depth;
2137 int max_loop_depth = irp->max_callgraph_loop_depth;
2138 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2140 int my_rec_color = compute_color(rec_depth, max_rec_depth);
2141 int my_loop_color = compute_color(loop_depth, max_loop_depth);
2142 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2144 return my_overall_color;
2147 void dump_callgraph(const char *suffix) {
2149 int i, n_irgs = get_irp_n_irgs();
2150 int rem = edge_label;
2152 //ident *prefix = new_id_from_str("java/");
2154 F = vcg_open_name("Callgraph", suffix);
2155 dump_vcg_header(F, "Callgraph", NULL);
2157 for (i = 0; i < n_irgs; ++i) {
2158 ir_graph *irg = get_irp_irg(i);
2159 entity *ent = get_irg_entity(irg);
2160 int j, n_callees = get_irg_n_callees(irg);
2162 /* Do not dump runtime system. */
2163 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2165 dump_entity_node(F, ent, get_entity_color(ent));
2166 for (j = 0; j < n_callees; ++j) {
2167 entity *c = get_irg_entity(get_irg_callee(irg, j));
2168 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2169 int be = is_irg_callee_backedge(irg, j);
2172 "label:\"recursion %d\" color: %d" :
2173 "label:\"calls %d\" color: %d";
2174 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2182 /* Dump all irgs in interprocedural view to a single file. */
2183 void dump_all_cg_block_graph(const char *suffix) {
2186 int rem_view = interprocedural_view;
2187 interprocedural_view = 1;
2189 f = vcg_open_name("All_graphs", suffix);
2190 dump_vcg_header(f, "All_graphs", NULL);
2192 /* collect nodes in all irgs reachable in call graph*/
2193 for (i = 0; i < get_irp_n_irgs(); i++)
2194 ird_set_irg_link(get_irp_irg(i), NULL);
2196 cg_walk(clear_link, collect_node, NULL);
2198 /* dump all graphs */
2199 for (i = 0; i < get_irp_n_irgs(); i++) {
2200 current_ir_graph = get_irp_irg(i);
2201 assert(ird_get_irg_link(current_ir_graph));
2202 dump_graph(f, current_ir_graph);
2203 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2207 interprocedural_view = rem_view;
2210 /***********************************************************************/
2211 /* the following routines dumps type information without any ir nodes. */
2212 /***********************************************************************/
2215 dump_type_graph (ir_graph *irg, const char *suffix)
2219 rem = current_ir_graph;
2221 /* if a filter is set, dump only the irg's that match the filter */
2222 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2224 current_ir_graph = irg;
2226 f = vcg_open(irg, suffix, "-type");
2227 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2229 /* walk over the blocks in the graph */
2230 type_walk_irg(irg, dump_type_info, NULL, f);
2231 /* The walker for the const code can be called several times for the
2232 same (sub) experssion. So that no nodes are dumped several times
2233 we decrease the visited flag of the corresponding graph after each
2234 walk. So now increase it finally. */
2235 inc_irg_visited(get_const_code_irg());
2238 current_ir_graph = rem;
2242 dump_all_types (const char *suffix)
2244 FILE *f = vcg_open_name("All_types", suffix);
2245 dump_vcg_header(f, "All_types", NULL);
2246 type_walk(dump_type_info, NULL, f);
2247 inc_irg_visited(get_const_code_irg());
2252 dump_class_hierarchy (bool entities, const char *suffix)
2254 FILE *f = vcg_open_name("class_hierarchy", suffix);
2258 dump_vcg_header(f, "class_hierarchy", NULL);
2263 type_walk(dump_class_hierarchy_node, NULL, &env);
2267 /***********************************************************************/
2268 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2270 /* dump_ir_block_graph */
2272 /* dump_type_graph */
2273 /* dump_ir_graph_w_types */
2274 /***********************************************************************/
2276 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2278 for (i=0; i < get_irp_n_irgs(); i++) {
2279 dmp_grph(get_irp_irg(i), suffix);
2284 /**********************************************************************************
2285 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2286 * packed together in one subgraph/box *
2287 **********************************************************************************/
2289 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2290 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2292 ir_loop *son = NULL;
2294 /* Dump a new loop node. */
2295 dump_loop_node(F, loop);
2297 /* Dump the loop elements. */
2299 for(i = 0; i < get_loop_n_elements(loop); i++) {
2300 le = get_loop_element(loop, i);
2302 if (get_kind(son) == k_ir_loop) {
2304 /* We are a loop son -> Recurse */
2306 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2307 fprintf(F, "\" }\n");
2308 fprintf (F, "edge: {sourcename: \"");
2310 fprintf (F, "\" targetname: \"");
2312 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2313 loop_node_started = 0;
2315 dump_loop_son_edge(F, loop, son_number++);
2316 dump_loops_standalone(F, son);
2317 } else if (get_kind(son) == k_ir_node) {
2318 /* We are a loop node -> Collect firm nodes */
2320 ir_node *n = le.node;
2323 if (!loop_node_started) {
2324 /* Start a new node which contains all firm nodes of the current loop */
2325 fprintf (F, "node: { title: \"");
2327 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2328 loop_node_started = 1;
2334 bad |= dump_node_opcode(F, n);
2335 bad |= dump_node_mode(F, n);
2336 bad |= dump_node_typeinfo(F, n);
2338 bad |= dump_node_nodeattr(F, n);
2339 fprintf (F, " %ld", get_irn_node_nr(n));
2340 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2341 } else { /* for callgraph loop tree */
2342 assert(get_kind(son) == k_ir_graph);
2343 /* We are a loop node -> Collect firm graphs */
2344 ir_graph *n = (ir_graph *)le.node;
2345 if (!loop_node_started) {
2346 /* Start a new node which contains all firm nodes of the current loop */
2347 fprintf (F, "node: { title: \"");
2349 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2350 loop_node_started = 1;
2355 fprintf (F, " %s", get_irg_dump_name(n));
2356 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2360 if (loop_node_started) {
2361 fprintf(F, "\" }\n");
2362 fprintf (F, "edge: {sourcename: \"");
2364 fprintf (F, "\" targetname: \"");
2366 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2367 loop_node_started = 0;
2371 void dump_loop_tree(ir_graph *irg, const char *suffix)
2374 ir_graph *rem = current_ir_graph;
2375 int el_rem = edge_label;
2378 /* if a filter is set, dump only the irg's that match the filter */
2379 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2382 current_ir_graph = irg;
2384 f = vcg_open(irg, suffix, "-looptree");
2385 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2387 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2391 edge_label = el_rem;
2392 current_ir_graph = rem;
2395 void dump_callgraph_loop_tree(const char *suffix) {
2397 F = vcg_open_name("Callgraph_looptree", suffix);
2398 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2399 dump_loops_standalone(F, irp->outermost_cg_loop);
2404 /*******************************************************************************/
2405 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2406 /*******************************************************************************/
2408 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2409 int i, son_number = 0, node_number = 0;
2411 if (dump_loop_information_flag) dump_loop_node(F, loop);
2413 for (i = 0; i < get_loop_n_elements(loop); i++) {
2414 loop_element le = get_loop_element(loop, i);
2415 if (*(le.kind) == k_ir_loop) {
2416 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2418 collect_nodeloop(F, le.son, loopnodes);
2420 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2421 eset_insert(loopnodes, le.node);
2426 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2429 for(i = 0; i < get_loop_n_elements(loop); i++) {
2430 loop_element le = get_loop_element(loop, i);
2431 if (*(le.kind) == k_ir_loop) {
2433 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2435 if (is_Block(le.node)) start = 0; else start = -1;
2436 for (j = start; j < get_irn_arity(le.node); j++) {
2437 ir_node *pred = get_irn_n(le.node, j);
2438 if (!eset_contains(loopnodes, pred)) {
2439 eset_insert(extnodes, pred);
2440 if (!is_Block(pred)) {
2441 pred = get_nodes_block(pred);
2442 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2450 void dump_loop(ir_loop *l, const char *suffix) {
2453 eset *loopnodes = eset_create();
2454 eset *extnodes = eset_create();
2457 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2458 F = vcg_open_name (name, suffix);
2459 dump_vcg_header(F, name, NULL);
2461 /* collect all nodes to dump */
2462 collect_nodeloop(F, l, loopnodes);
2463 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2465 /* build block lists */
2466 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2467 set_irn_link(n, NULL);
2468 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2469 set_irn_link(n, NULL);
2470 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2472 b = get_nodes_block(n);
2473 set_irn_link(n, get_irn_link(b));
2476 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2478 b = get_nodes_block(n);
2479 set_irn_link(n, get_irn_link(b));
2483 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2485 fprintf(F, "graph: { title: \"");
2487 fprintf(F, "\" label: \"");
2488 dump_node_opcode(F, b);
2489 fprintf (F, " %ld", get_irn_node_nr(b));
2490 fprintf(F, "\" status:clustered color:yellow\n");
2492 /* dump the blocks edges */
2493 dump_ir_data_edges(F, b);
2495 /* dump the nodes that go into the block */
2496 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2497 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2499 overrule_nodecolor = NULL;
2500 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2503 /* Close the vcg information for the block */
2505 dump_const_node_local(F, b);
2508 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2510 fprintf(F, "graph: { title: \"");
2512 fprintf(F, "\" label: \"");
2513 dump_node_opcode(F, b);
2514 fprintf (F, " %ld", get_irn_node_nr(b));
2515 fprintf(F, "\" status:clustered color:lightblue\n");
2517 /* dump the nodes that go into the block */
2518 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2519 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2521 overrule_nodecolor = NULL;
2522 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2525 /* Close the vcg information for the block */
2527 dump_const_node_local(F, b);
2531 eset_destroy(loopnodes);
2532 eset_destroy(extnodes);