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))));
817 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
818 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
819 if (get_irn_type(n) != none_type)
820 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
829 bool is_constlike_node(ir_node *n) {
830 ir_op *op = get_irn_op(n);
831 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
835 /* outputs the predecessors of n, that are constants, local. I.e.,
836 generates a copy of the constant predecessors for each node called with. */
837 static void dump_const_node_local(FILE *F, ir_node *n) {
839 if (!get_opt_dump_const_local()) return;
841 /* Use visited flag to avoid outputting nodes twice.
842 initialize it first. */
843 for (i = 0; i < get_irn_arity(n); i++) {
844 ir_node *con = get_irn_n(n, i);
845 if (is_constlike_node(con)) {
846 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
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) && irn_not_visited(con)) {
855 mark_irn_visited(con);
856 /* Generate a new name for the node by appending the names of
858 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
859 fprintf(F, " label: \"");
860 bad |= dump_node_opcode(F, con);
861 bad |= dump_node_mode(F, con);
862 bad |= dump_node_typeinfo(F, con);
864 bad |= dump_node_nodeattr(F, con);
865 fprintf(F, " %ld", get_irn_node_nr(con));
867 bad |= dump_node_info(F, con);
868 dump_node_vcgattr(F, con, bad);
874 static void INLINE print_node_error(FILE *F, const char *p)
879 fprintf (F, " info2: \"%s\"", p);
882 static void dump_node(FILE *F, ir_node *n)
887 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
889 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
891 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
892 bad |= dump_node_opcode(F, n);
893 bad |= dump_node_mode(F, n);
894 bad |= dump_node_typeinfo(F, n);
896 bad |= dump_node_nodeattr(F, n);
897 fprintf(F, " %ld", get_irn_node_nr(n));
899 bad |= dump_node_info(F, n);
900 print_node_error(F, p);
901 dump_node_vcgattr(F, n, bad);
903 dump_const_node_local(F, n);
910 /* dump the edge to the block this node belongs to */
912 dump_ir_block_edge(FILE *F, ir_node *n) {
913 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
914 if (is_no_Block(n)) {
915 ir_node *block = get_nodes_block(n);
917 fprintf (F, "edge: { sourcename: \"");
919 fprintf (F, "\" targetname: ");
920 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
921 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
926 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
927 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
928 fprintf (F, INTRA_DATA_EDGE_ATTR);
930 fprintf (F, INTER_DATA_EDGE_ATTR);
934 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
935 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
936 fprintf (F, INTRA_MEM_EDGE_ATTR);
938 fprintf (F, INTER_MEM_EDGE_ATTR);
942 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
945 if (dump_backedge_information_flag && is_backedge(from, to))
946 fprintf (F, BACK_EDGE_ATTR);
948 switch (get_irn_opcode(from)) {
950 fprintf (F, CF_EDGE_ATTR);
952 case iro_Start: break;
955 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
956 fprintf (F, CF_EDGE_ATTR);
957 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
958 fprintf (F, INTER_MEM_EDGE_ATTR);
966 print_data_edge_vcgattr(F, from, to);
971 print_mem_edge_vcgattr(F, from, to);
973 print_data_edge_vcgattr(F, from, to);
977 print_data_edge_vcgattr(F, from, to);
982 print_mem_edge_vcgattr(F, from, to);
984 print_data_edge_vcgattr(F, from, to);
991 print_data_edge_vcgattr(F, from, to);
998 print_mem_edge_vcgattr(F, from, to);
1000 print_data_edge_vcgattr(F, from, to);
1012 print_data_edge_vcgattr(F, from, to);
1015 if (get_irn_modecode(from) == irm_M)
1016 fprintf (F, INTER_MEM_EDGE_ATTR);
1018 print_data_edge_vcgattr(F, from, to);
1025 print_mem_edge_vcgattr(F, from, to);
1027 print_data_edge_vcgattr(F, from, to);
1030 print_mem_edge_vcgattr(F, from, to);
1032 case iro_Tuple: break;
1035 switch (get_irn_modecode(from)) {
1037 fprintf (F, CF_EDGE_ATTR);
1040 fprintf (F, INTER_MEM_EDGE_ATTR);
1043 print_data_edge_vcgattr(F, from, to);
1047 case iro_Bad: break;
1048 case iro_Unknown: break;
1050 switch (get_irn_modecode(from)) {
1052 fprintf (F, INTRA_MEM_EDGE_ATTR);
1055 fprintf (F, CF_EDGE_ATTR);
1058 print_data_edge_vcgattr(F, from, to);
1066 /* dump edges to our inputs */
1068 dump_ir_data_edges(FILE *F, ir_node *n) {
1069 int i, visited = get_irn_visited(n);
1071 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1074 for (i = 0; i < get_irn_arity(n); i++) {
1075 ir_node * pred = get_irn_n(n, i);
1078 if ((interprocedural_view && get_irn_visited(pred) < visited))
1079 continue; /* pred not dumped */
1081 if (dump_backedge_information_flag && is_backedge(n, i))
1082 fprintf (F, "backedge: {sourcename: \"");
1084 fprintf (F, "edge: {sourcename: \"");
1086 fprintf (F, "\" targetname: ");
1087 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1088 PRINT_CONSTID(n, pred);
1090 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1092 fprintf (F, " label: \"%d\" ", i);
1093 print_edge_vcgattr(F, n, i);
1098 /** Dumps a node and its edges but not the block edge
1101 dump_node_wo_blockedge (ir_node *n, void *env) {
1104 dump_ir_data_edges(F, n);
1107 /** Dumps a node and its edges.
1110 dump_whole_node (ir_node *n, void *env) {
1112 dump_node_wo_blockedge(n, env);
1113 if (!node_floats(n)) dump_ir_block_edge(F, n);
1117 dump_const_node(ir_node *n, void *env) {
1118 if (is_Block(n)) return;
1119 dump_node_wo_blockedge(n, env);
1122 /***********************************************************************/
1123 /* the following routines dump the nodes/irgs bracketed to graphs. */
1124 /***********************************************************************/
1126 /** Dumps a constant expression as entity initializer, array bound ...
1128 static void dump_const_expression(FILE *F, ir_node *value) {
1129 ir_graph *rem = current_ir_graph;
1130 int rem_dump_const_local = dump_const_local;
1131 dump_const_local = 0;
1132 current_ir_graph = get_const_code_irg();
1133 irg_walk(value, dump_const_node, NULL, F);
1134 /* Decrease visited flag so that we walk with the same flag for the next
1135 expresssion. This guarantees that we don't dump the same node twice,
1136 as for const expressions cse is performed to save memory. */
1137 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1138 current_ir_graph = rem;
1139 dump_const_local = rem_dump_const_local;
1142 /** Dump a block as graph containing its nodes.
1144 * Expects to find nodes belonging to the block as list in its
1146 * Dumps the edges of all nodes including itself. */
1148 dump_whole_block(FILE *F, ir_node *block) {
1150 assert(is_Block(block));
1152 fprintf(F, "graph: { title: \"");
1153 PRINT_NODEID(block);
1154 fprintf(F, "\" label: \"");
1155 dump_node_opcode(F, block);
1156 fprintf (F, " %ld", get_irn_node_nr(block));
1158 if (get_opt_dump_abstvals())
1159 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1161 fprintf(F, "\" status:clustered color:%s \n",
1162 get_Block_matured(block) ? "yellow" : "red");
1164 /* dump the blocks edges */
1165 dump_ir_data_edges(F, block);
1167 /* dump the nodes that go into the block */
1168 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1170 dump_ir_data_edges(F, node);
1173 /* Close the vcg information for the block */
1175 dump_const_node_local(F, block);
1177 dump_chi_term(F, block);
1182 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1183 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1185 dump_block_graph(FILE *F, ir_graph *irg) {
1187 ir_graph *rem = current_ir_graph;
1188 ir_node **arr = ird_get_irg_link(irg);
1189 current_ir_graph = irg;
1191 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1192 ir_node * node = arr[i];
1193 if (is_Block(node)) {
1194 /* Dumps the block and all the nodes in the block, which are to
1195 be found in Block->link. */
1196 dump_whole_block(F, node);
1198 /* Nodes that are not in a Block. */
1200 dump_ir_data_edges(F, node);
1204 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1205 dump_loop_nodes_into_graph(F, irg);
1207 current_ir_graph = rem;
1210 /** Dumps an irg as a graph.
1211 * If interprocedural view edges can point to nodes out of this graph.
1213 static void dump_graph(FILE *F, ir_graph *irg) {
1215 fprintf(F, "graph: { title: \"");
1217 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1218 get_ent_dump_name(get_irg_entity(irg)));
1220 dump_block_graph(F, irg);
1222 /* Close the vcg information for the irg */
1223 fprintf(F, "}\n\n");
1226 /*******************************************************************/
1227 /* Basic type and entity nodes and edges. */
1228 /*******************************************************************/
1230 /* dumps the edges between nodes and their type or entity attributes. */
1231 static void dump_node2type_edges(ir_node *n, void *env)
1236 switch (get_irn_opcode(n)) {
1238 /* @@@ some consts have an entity */
1241 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1242 || (get_SymConst_kind(n) ==symconst_size))
1244 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1248 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1251 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1254 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1257 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1260 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1268 static int print_type_info(FILE *F, type *tp) {
1271 if (get_type_state(tp) == layout_undefined) {
1272 fprintf(F, "state: layout_undefined\n");
1274 fprintf(F, "state: layout_fixed,\n");
1276 if (get_type_mode(tp))
1277 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1278 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1283 static void print_typespecific_info(FILE *F, type *tp) {
1284 switch (get_type_tpop_code(tp)) {
1287 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1294 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1295 fprintf(F, "params: %d\n", get_method_n_params(tp));
1296 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1304 case tpo_enumeration:
1318 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1319 switch (get_type_tpop_code(tp)) {
1322 if (peculiarity_existent == get_class_peculiarity(tp))
1323 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1325 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1329 fprintf (F, " " TYPE_METH_NODE_ATTR);
1340 case tpo_enumeration:
1353 static int print_type_node(FILE *F, type *tp)
1357 fprintf (F, "node: {title: ");
1359 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1360 fprintf (F, " info1: \"");
1361 bad |= print_type_info(F, tp);
1362 print_typespecific_info(F, tp);
1364 print_typespecific_vcgattr(F, tp);
1370 #define X(a) case a: fprintf(F, #a); break
1371 void dump_entity_node(FILE *F, entity *ent, int color)
1373 fprintf (F, "node: {title: \"");
1374 PRINT_ENTID(ent); fprintf(F, "\"");
1375 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1376 fprintf (F, "label: ");
1377 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1379 fprintf(F, "color: %d", color);
1381 fprintf (F, ENTITY_NODE_ATTR);
1382 fprintf (F, "\n info1: \"");
1384 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1386 fprintf(F, "\"\n}\n");
1390 static void dump_enum_item(FILE *F, type *tp, int pos)
1393 ident *id = get_enumeration_nameid(tp, pos);
1394 tarval *tv = get_enumeration_enum(tp, pos);
1396 tarval_snprintf(buf, sizeof(buf), tv);
1397 fprintf (F, "node: {title: \"");
1398 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1399 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1400 fprintf (F, "label: ");
1401 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1402 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1405 /* dumps a type or entity and it's edges. */
1407 dump_type_info(type_or_ent *tore, void *env) {
1409 int i = 0; /* to shutup gcc */
1411 /* dump this type or entity */
1413 switch (get_kind(tore)) {
1416 entity *ent = (entity *)tore;
1419 dump_entity_node(F, ent, 0);
1421 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1422 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1423 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1424 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1425 if(is_class_type(get_entity_owner(ent))) {
1426 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1427 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1429 /* attached subgraphs */
1430 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1431 if (is_atomic_entity(ent)) {
1432 value = get_atomic_ent_value(ent);
1434 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1435 /* DDMN(value); $$$ */
1436 dump_const_expression(F, value);
1439 if (is_compound_entity(ent)) {
1440 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1441 value = get_compound_ent_value(ent, i);
1443 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1444 dump_const_expression(F, value);
1445 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1447 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1448 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1449 get_compound_ent_value_member(ent, i), i);
1458 type *tp = (type *)tore;
1459 print_type_node(F, tp);
1460 /* and now the edges */
1461 switch (get_type_tpop_code(tp)) {
1464 for (i=0; i < get_class_n_supertypes(tp); i++)
1465 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1466 for (i=0; i < get_class_n_members(tp); i++)
1467 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1471 for (i=0; i < get_struct_n_members(tp); i++)
1472 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1476 for (i = 0; i < get_method_n_params(tp); i++)
1477 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1478 for (i = 0; i < get_method_n_ress(tp); i++)
1479 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1483 for (i = 0; i < get_union_n_members(tp); i++)
1484 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1488 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1489 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1490 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1491 ir_node *upper = get_array_upper_bound(tp, i);
1492 ir_node *lower = get_array_lower_bound(tp, i);
1493 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1494 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1495 dump_const_expression(F, upper);
1496 dump_const_expression(F, lower);
1500 case tpo_enumeration:
1502 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1503 dump_enum_item(F, tp, i);
1504 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1509 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1517 break; /* case k_type */
1520 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1522 } /* switch kind_or_entity */
1525 typedef struct _h_env {
1530 /** For dumping class hierarchies.
1531 * Dumps a class type node and a superclass edge.
1532 * If env->dump_ent dumps entities of classes and overwrites edges.
1535 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1538 int i = 0; /* to shutup gcc */
1540 /* dump this type or entity */
1541 switch (get_kind(tore)) {
1543 entity *ent = (entity *)tore;
1544 if (get_entity_owner(ent) == get_glob_type()) break;
1545 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1546 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1548 dump_entity_node(F, ent, 0);
1550 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1551 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1552 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1554 } break; /* case k_entity */
1557 type *tp = (type *)tore;
1558 if (tp == get_glob_type()) break;
1559 switch (get_type_tpop_code(tp)) {
1561 print_type_node(F, tp);
1562 /* and now the edges */
1563 for (i=0; i < get_class_n_supertypes(tp); i++)
1565 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1571 break; /* case k_type */
1574 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1576 } /* switch kind_or_entity */
1579 /*******************************************************************/
1580 /* dump analysis information that is expressed in graph terms. */
1581 /*******************************************************************/
1583 /* dump out edges */
1585 dump_out_edge(ir_node *n, void *env) {
1588 for (i = 0; i < get_irn_n_outs(n); i++) {
1589 assert(get_irn_out(n, i));
1590 fprintf (F, "edge: {sourcename: \"");
1592 fprintf (F, "\" targetname: \"");
1593 PRINT_NODEID(get_irn_out(n, i));
1594 fprintf (F, "\" color: red linestyle: dashed");
1600 dump_loop_label(FILE *F, ir_loop *loop) {
1601 fprintf (F, "loop %d, %d sons, %d nodes",
1602 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1605 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1606 fprintf (F, " info1: \"");
1607 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1608 #if DEBUG_libfirm /* GL @@@ debug analyses */
1609 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1615 dump_loop_node(FILE *F, ir_loop *loop) {
1616 fprintf (F, "node: {title: \"");
1618 fprintf (F, "\" label: \"");
1619 dump_loop_label(F, loop);
1621 dump_loop_info(F, loop);
1627 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1629 fprintf (F, "edge: {sourcename: \"");
1631 fprintf (F, "\" targetname: \"");
1632 PRINT_NODEID(get_loop_node(loop, i));
1633 fprintf (F, "\" color: green");
1638 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1640 fprintf (F, "edge: {sourcename: \"");
1642 fprintf (F, "\" targetname: \"");
1643 PRINT_LOOPID(get_loop_son(loop, i));
1644 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1645 get_loop_element_pos(loop, get_loop_son(loop, i)));
1649 void dump_loops(FILE *F, ir_loop *loop) {
1651 /* dump this loop node */
1652 dump_loop_node(F, loop);
1654 /* dump edges to nodes in loop -- only if it is a real loop */
1655 if (get_loop_depth(loop) != 0) {
1656 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1657 dump_loop_node_edge(F, loop, i);
1660 for (i = 0; i < get_loop_n_sons(loop); i++) {
1661 dump_loops(F, get_loop_son(loop, i));
1662 dump_loop_son_edge(F, loop, i);
1667 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1668 ir_graph *rem = current_ir_graph;
1669 current_ir_graph = irg;
1671 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1673 current_ir_graph = rem;
1678 * dumps the VCG header
1681 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1690 if (!orientation) orientation = "bottom_to_top";
1694 "graph: { title: \"ir graph of %s\"\n"
1695 "display_edge_labels: %s\n"
1696 "layoutalgorithm: mindepth\n"
1697 "manhattan_edges: yes\n"
1698 "port_sharing: no\n"
1700 "classname 1: \"intrablock Data\"\n"
1701 "classname 16: \"interblock Data\"\n"
1702 "classname 2: \"Block\"\n"
1703 "classname 13: \"Control Flow\"\n"
1704 "classname 14: \"intrablock Memory\"\n"
1705 "classname 17: \"interblock Memory\"\n"
1706 "classname 15: \"Dominators\"\n"
1707 "classname 3: \"Entity type\"\n"
1708 "classname 4: \"Entity owner\"\n"
1709 "classname 5: \"Method Param\"\n"
1710 "classname 6: \"Method Res\"\n"
1711 "classname 7: \"Super\"\n"
1712 "classname 8: \"Union\"\n"
1713 "classname 9: \"Points-to\"\n"
1714 "classname 10: \"Array Element Type\"\n"
1715 "classname 11: \"Overwrites\"\n"
1716 "classname 12: \"Member\"\n"
1717 "infoname 1: \"Attribute\"\n"
1718 "infoname 2: \"Verification errors\"\n",
1719 name, label, orientation);
1721 /* don't use all, the range is too whith/black. */
1725 "colorentry 100: 0 0 0\n"
1726 "colorentry 101: 20 0 0\n"
1727 "colorentry 102: 40 0 0\n"
1728 "colorentry 103: 60 0 0\n"
1729 "colorentry 104: 80 0 0\n"
1730 "colorentry 105: 100 0 0\n"
1731 "colorentry 106: 120 0 0\n"
1732 "colorentry 107: 140 0 0\n"
1733 "colorentry 108: 150 0 0\n"
1734 "colorentry 109: 180 0 0\n"
1735 "colorentry 110: 200 0 0\n"
1736 "colorentry 111: 220 0 0\n"
1737 "colorentry 112: 240 0 0\n"
1738 "colorentry 113: 255 0 0\n"
1739 "colorentry 113: 255 20 20\n"
1740 "colorentry 114: 255 40 40\n"
1741 "colorentry 115: 255 60 60\n"
1742 "colorentry 116: 255 80 80\n"
1743 "colorentry 117: 255 100 100\n"
1744 "colorentry 118: 255 120 120\n"
1745 "colorentry 119: 255 140 140\n"
1746 "colorentry 120: 255 150 150\n"
1747 "colorentry 121: 255 180 180\n"
1748 "colorentry 122: 255 200 200\n"
1749 "colorentry 123: 255 220 220\n"
1750 "colorentry 124: 255 240 240\n"
1751 "colorentry 125: 255 250 250\n"
1754 fprintf (F, "\n"); /* a separator */
1760 * @param irg The graph to be dumped
1761 * @param suffix1 first filename suffix
1762 * @param suffix2 second filename suffix
1764 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1766 const char *nm = get_irg_dump_name(irg);
1767 int len = strlen(nm), i, j;
1768 char *fname; /* filename to put the vcg information in */
1770 if (!suffix1) suffix1 = "";
1771 if (!suffix2) suffix2 = "";
1773 /* open file for vcg graph */
1774 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1776 /* strncpy (fname, nm, len); */ /* copy the filename */
1778 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1780 fname[j] = '@'; j++; fname[j] = '1'; j++;
1781 } else if (nm[i] == '@') {
1782 fname[j] = '@'; j++; fname[j] = '2'; j++;
1784 fname[j] = nm[i]; j++;
1788 strcat (fname, suffix1); /* append file suffix */
1789 strcat (fname, suffix2); /* append file suffix */
1790 strcat (fname, ".vcg"); /* append the .vcg suffix */
1791 F = fopen (fname, "w"); /* open file for writing */
1793 panic("cannot open %s for writing (%m)", fname); /* not reached */
1803 * @param irg The graph to be dumped
1804 * @param suffix filename suffix
1806 static FILE *vcg_open_name (const char *name, const char *suffix) {
1808 char *fname; /* filename to put the vcg information in */
1809 int i, j, len = strlen(name);
1811 if (!suffix) suffix = "";
1813 /** open file for vcg graph */
1814 fname = malloc (len * 2 + 5 + strlen(suffix));
1815 /* strcpy (fname, name);*/ /* copy the filename */
1817 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1818 if (name[i] == '/') {
1819 fname[j] = '@'; j++; fname[j] = '1'; j++;
1820 } else if (name[i] == '@') {
1821 fname[j] = '@'; j++; fname[j] = '2'; j++;
1823 fname[j] = name[i]; j++;
1827 strcat (fname, suffix);
1828 strcat (fname, ".vcg"); /* append the .vcg suffix */
1829 F = fopen (fname, "w"); /* open file for writing */
1831 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1839 * Dumps the vcg file footer
1841 static INLINE void dump_vcg_footer (FILE *F) {
1846 * close the vcg file
1849 vcg_close (FILE *F) {
1850 dump_vcg_footer(F); /* print footer */
1851 fclose (F); /* close vcg file */
1854 /************************************************************************/
1855 /************************************************************************/
1856 /* Routines that dump all or parts of the firm representation to a file */
1857 /************************************************************************/
1858 /************************************************************************/
1860 /************************************************************************/
1861 /* Dump ir graphs, differnt formats and additional information. */
1862 /************************************************************************/
1864 /** Routine to dump a graph, blocks as conventional nodes.
1867 dump_ir_graph (ir_graph *irg, const char *suffix )
1872 rem = current_ir_graph;
1874 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1875 current_ir_graph = irg;
1876 if (interprocedural_view) suffix1 = "-pure-ip";
1877 else suffix1 = "-pure";
1878 f = vcg_open(irg, suffix, suffix1);
1879 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1881 /* walk over the graph */
1882 /* dump_whole_node must be called in post visiting predecessors */
1883 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1885 /* dump the out edges in a separate walk */
1886 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1887 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1892 current_ir_graph = rem;
1897 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1903 if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1904 if (interprocedural_view) suffix1 = "-ip";
1906 f = vcg_open(irg, suffix, suffix1);
1907 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1909 construct_block_lists(irg);
1911 for (i = 0; i < get_irp_n_irgs(); i++) {
1912 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1914 dump_graph(f, get_irp_irg(i));
1922 /** dumps a graph with type information
1925 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1928 ir_graph *rem = current_ir_graph;
1931 /* if a filter is set, dump only the irg's that match the filter */
1932 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1935 current_ir_graph = irg;
1937 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1938 else suffix1 = "-pure-wtypes";
1939 f = vcg_open(irg,suffix, suffix1);
1940 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1942 /* dump common ir graph */
1943 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1944 /* dump type info */
1945 type_walk_irg(irg, dump_type_info, NULL, f);
1946 inc_irg_visited(get_const_code_irg());
1947 /* dump edges from graph to type info */
1948 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1951 current_ir_graph = rem;
1955 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1960 ir_graph *rem = current_ir_graph;
1962 /* if a filter is set, dump only the irg's that match the filter */
1963 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1966 if (interprocedural_view) suffix1 = "-wtypes-ip";
1967 else suffix1 = "-wtypes";
1968 f = vcg_open(irg, suffix, suffix1);
1969 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1971 /* dump common blocked ir graph */
1972 construct_block_lists(irg);
1974 for (i = 0; i < get_irp_n_irgs(); i++) {
1975 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1977 dump_graph(f, get_irp_irg(i));
1982 /* dump type info */
1983 current_ir_graph = irg;
1984 type_walk_irg(irg, dump_type_info, NULL, f);
1985 inc_irg_visited(get_const_code_irg());
1987 /* dump edges from graph to type info */
1988 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1990 current_ir_graph = rem;
1994 /*---------------------------------------------------------------------*/
1995 /* The following routines dump a control flow graph. */
1996 /*---------------------------------------------------------------------*/
1999 dump_block_to_cfg(ir_node *block, void *env) {
2004 if (is_Block(block)) {
2005 /* This is a block. Dump a node for the block. */
2006 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2007 fprintf (F, "\" label: \"");
2008 if (block == get_irg_start_block(get_irn_irg(block)))
2009 fprintf(F, "Start ");
2010 if (block == get_irg_end_block(get_irn_irg(block)))
2013 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2014 PRINT_NODEID(block);
2016 fprintf(F, "info1:\"");
2017 if (dump_dominator_information_flag)
2018 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2020 /* show arity and possible Bad predecessors of the block */
2021 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2022 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2023 ir_node *pred = get_Block_cfgpred(block, i);
2026 fprintf(F, "Bad pred at pos: ");
2027 fprintf(F, "%d ", i);
2034 fprintf (F, "\""); /* closing quote of info */
2036 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2037 (block == get_irg_end_block(get_irn_irg(block))) )
2038 fprintf(F, " color:blue ");
2040 fprintf(F, " color:yellow ");
2043 /* Dump the edges */
2044 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2045 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2046 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2047 fprintf (F, "edge: { sourcename: \"");
2048 PRINT_NODEID(block);
2049 fprintf (F, "\" targetname: \"");
2051 fprintf (F, "\"}\n");
2054 /* Dump dominator edge */
2055 if (dump_dominator_information_flag && get_Block_idom(block)) {
2056 pred = get_Block_idom(block);
2057 fprintf (F, "edge: { sourcename: \"");
2058 PRINT_NODEID(block);
2059 fprintf (F, "\" targetname: \"");
2061 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2067 dump_cfg (ir_graph *irg, const char *suffix)
2070 ir_graph *rem = current_ir_graph;
2071 int ddif = dump_dominator_information_flag;
2072 int ipv = interprocedural_view;
2074 /* if a filter is set, dump only the irg's that match the filter */
2075 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2078 current_ir_graph = irg;
2080 f = vcg_open(irg, suffix, "-cfg");
2081 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2083 if (interprocedural_view) {
2084 printf("Warning: dumping cfg not in interprocedural view!\n");
2085 interprocedural_view = 0;
2088 if (get_irg_dom_state(irg) != dom_consistent)
2089 dump_dominator_information_flag = 0;
2091 /* walk over the blocks in the graph */
2092 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2093 dump_node(f, get_irg_bad(irg));
2095 dump_dominator_information_flag = ddif;
2096 interprocedural_view = ipv;
2098 current_ir_graph = rem;
2101 static int weight_overall(int rec, int loop) {
2102 return 2*rec + loop;
2105 static int compute_color (int my, int max) {
2110 /* if small, scale to the full color range. */
2112 my = my * (n_colors/max);
2114 int step = 1 + (max / n_colors);
2118 return base_color + n_colors - color;
2121 static int get_entity_color(entity *ent) {
2122 assert(get_entity_irg(ent));
2123 ir_graph *irg = get_entity_irg(ent);
2125 int rec_depth = get_irg_recursion_depth(irg);
2126 int loop_depth = get_irg_loop_depth(irg);
2127 int overall_depth = weight_overall(rec_depth, loop_depth);
2129 int max_rec_depth = irp->max_callgraph_recursion_depth;
2130 int max_loop_depth = irp->max_callgraph_loop_depth;
2131 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2133 int my_rec_color = compute_color(rec_depth, max_rec_depth);
2134 int my_loop_color = compute_color(loop_depth, max_loop_depth);
2135 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2137 return my_overall_color;
2140 void dump_callgraph(const char *suffix) {
2142 int i, n_irgs = get_irp_n_irgs();
2143 int rem = edge_label;
2145 //ident *prefix = new_id_from_str("java/");
2147 F = vcg_open_name("Callgraph", suffix);
2148 dump_vcg_header(F, "Callgraph", NULL);
2150 for (i = 0; i < n_irgs; ++i) {
2151 ir_graph *irg = get_irp_irg(i);
2152 entity *ent = get_irg_entity(irg);
2153 int j, n_callees = get_irg_n_callees(irg);
2155 /* Do not dump runtime system. */
2156 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2158 dump_entity_node(F, ent, get_entity_color(ent));
2159 for (j = 0; j < n_callees; ++j) {
2160 entity *c = get_irg_entity(get_irg_callee(irg, j));
2161 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2162 int be = is_irg_callee_backedge(irg, j);
2165 "label:\"recursion %d\" color: %d" :
2166 "label:\"calls %d\" color: %d";
2167 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2175 /* Dump all irgs in interprocedural view to a single file. */
2176 void dump_all_cg_block_graph(const char *suffix) {
2179 int rem_view = interprocedural_view;
2180 interprocedural_view = 1;
2182 f = vcg_open_name("All_graphs", suffix);
2183 dump_vcg_header(f, "All_graphs", NULL);
2185 /* collect nodes in all irgs reachable in call graph*/
2186 for (i = 0; i < get_irp_n_irgs(); i++)
2187 ird_set_irg_link(get_irp_irg(i), NULL);
2189 cg_walk(clear_link, collect_node, NULL);
2191 /* dump all graphs */
2192 for (i = 0; i < get_irp_n_irgs(); i++) {
2193 current_ir_graph = get_irp_irg(i);
2194 assert(ird_get_irg_link(current_ir_graph));
2195 dump_graph(f, current_ir_graph);
2196 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2200 interprocedural_view = rem_view;
2203 /***********************************************************************/
2204 /* the following routines dumps type information without any ir nodes. */
2205 /***********************************************************************/
2208 dump_type_graph (ir_graph *irg, const char *suffix)
2212 rem = current_ir_graph;
2214 /* if a filter is set, dump only the irg's that match the filter */
2215 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2217 current_ir_graph = irg;
2219 f = vcg_open(irg, suffix, "-type");
2220 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2222 /* walk over the blocks in the graph */
2223 type_walk_irg(irg, dump_type_info, NULL, f);
2224 /* The walker for the const code can be called several times for the
2225 same (sub) experssion. So that no nodes are dumped several times
2226 we decrease the visited flag of the corresponding graph after each
2227 walk. So now increase it finally. */
2228 inc_irg_visited(get_const_code_irg());
2231 current_ir_graph = rem;
2235 dump_all_types (const char *suffix)
2237 FILE *f = vcg_open_name("All_types", suffix);
2238 dump_vcg_header(f, "All_types", NULL);
2239 type_walk(dump_type_info, NULL, f);
2240 inc_irg_visited(get_const_code_irg());
2245 dump_class_hierarchy (bool entities, const char *suffix)
2247 FILE *f = vcg_open_name("class_hierarchy", suffix);
2251 dump_vcg_header(f, "class_hierarchy", NULL);
2256 type_walk(dump_class_hierarchy_node, NULL, &env);
2260 /***********************************************************************/
2261 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2263 /* dump_ir_block_graph */
2265 /* dump_type_graph */
2266 /* dump_ir_graph_w_types */
2267 /***********************************************************************/
2269 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2271 for (i=0; i < get_irp_n_irgs(); i++) {
2272 dmp_grph(get_irp_irg(i), suffix);
2277 /**********************************************************************************
2278 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
2279 * packed together in one subgraph/box *
2280 **********************************************************************************/
2282 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2283 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2285 ir_loop *son = NULL;
2287 /* Dump a new loop node. */
2288 dump_loop_node(F, loop);
2290 /* Dump the loop elements. */
2292 for(i = 0; i < get_loop_n_elements(loop); i++) {
2293 le = get_loop_element(loop, i);
2295 if (get_kind(son) == k_ir_loop) {
2297 /* We are a loop son -> Recurse */
2299 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2300 fprintf(F, "\" }\n");
2301 fprintf (F, "edge: {sourcename: \"");
2303 fprintf (F, "\" targetname: \"");
2305 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2306 loop_node_started = 0;
2308 dump_loop_son_edge(F, loop, son_number++);
2309 dump_loops_standalone(F, son);
2310 } else if (get_kind(son) == k_ir_node) {
2311 /* We are a loop node -> Collect firm nodes */
2313 ir_node *n = le.node;
2316 if (!loop_node_started) {
2317 /* Start a new node which contains all firm nodes of the current loop */
2318 fprintf (F, "node: { title: \"");
2320 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2321 loop_node_started = 1;
2327 bad |= dump_node_opcode(F, n);
2328 bad |= dump_node_mode(F, n);
2329 bad |= dump_node_typeinfo(F, n);
2331 bad |= dump_node_nodeattr(F, n);
2332 fprintf (F, " %ld", get_irn_node_nr(n));
2333 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2334 } else { /* for callgraph loop tree */
2335 assert(get_kind(son) == k_ir_graph);
2336 /* We are a loop node -> Collect firm graphs */
2337 ir_graph *n = (ir_graph *)le.node;
2338 if (!loop_node_started) {
2339 /* Start a new node which contains all firm nodes of the current loop */
2340 fprintf (F, "node: { title: \"");
2342 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2343 loop_node_started = 1;
2348 fprintf (F, " %s", get_irg_dump_name(n));
2349 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2353 if (loop_node_started) {
2354 fprintf(F, "\" }\n");
2355 fprintf (F, "edge: {sourcename: \"");
2357 fprintf (F, "\" targetname: \"");
2359 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2360 loop_node_started = 0;
2364 void dump_loop_tree(ir_graph *irg, const char *suffix)
2367 ir_graph *rem = current_ir_graph;
2368 int el_rem = edge_label;
2371 /* if a filter is set, dump only the irg's that match the filter */
2372 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2375 current_ir_graph = irg;
2377 f = vcg_open(irg, suffix, "-looptree");
2378 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2380 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2384 edge_label = el_rem;
2385 current_ir_graph = rem;
2388 void dump_callgraph_loop_tree(const char *suffix) {
2390 F = vcg_open_name("Callgraph_looptree", suffix);
2391 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2392 dump_loops_standalone(F, irp->outermost_cg_loop);
2397 /*******************************************************************************/
2398 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2399 /*******************************************************************************/
2401 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2402 int i, son_number = 0, node_number = 0;
2404 if (dump_loop_information_flag) dump_loop_node(F, loop);
2406 for (i = 0; i < get_loop_n_elements(loop); i++) {
2407 loop_element le = get_loop_element(loop, i);
2408 if (*(le.kind) == k_ir_loop) {
2409 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2411 collect_nodeloop(F, le.son, loopnodes);
2413 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2414 eset_insert(loopnodes, le.node);
2419 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2422 for(i = 0; i < get_loop_n_elements(loop); i++) {
2423 loop_element le = get_loop_element(loop, i);
2424 if (*(le.kind) == k_ir_loop) {
2426 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2428 if (is_Block(le.node)) start = 0; else start = -1;
2429 for (j = start; j < get_irn_arity(le.node); j++) {
2430 ir_node *pred = get_irn_n(le.node, j);
2431 if (!eset_contains(loopnodes, pred)) {
2432 eset_insert(extnodes, pred);
2433 if (!is_Block(pred)) {
2434 pred = get_nodes_block(pred);
2435 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2443 void dump_loop(ir_loop *l, const char *suffix) {
2446 eset *loopnodes = eset_create();
2447 eset *extnodes = eset_create();
2450 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2451 F = vcg_open_name (name, suffix);
2452 dump_vcg_header(F, name, NULL);
2454 /* collect all nodes to dump */
2455 collect_nodeloop(F, l, loopnodes);
2456 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2458 /* build block lists */
2459 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2460 set_irn_link(n, NULL);
2461 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2462 set_irn_link(n, NULL);
2463 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2465 b = get_nodes_block(n);
2466 set_irn_link(n, get_irn_link(b));
2469 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2471 b = get_nodes_block(n);
2472 set_irn_link(n, get_irn_link(b));
2476 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2478 fprintf(F, "graph: { title: \"");
2480 fprintf(F, "\" label: \"");
2481 dump_node_opcode(F, b);
2482 fprintf (F, " %ld", get_irn_node_nr(b));
2483 fprintf(F, "\" status:clustered color:yellow\n");
2485 /* dump the blocks edges */
2486 dump_ir_data_edges(F, b);
2488 /* dump the nodes that go into the block */
2489 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2490 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2492 overrule_nodecolor = NULL;
2493 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2496 /* Close the vcg information for the block */
2498 dump_const_node_local(F, b);
2501 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2503 fprintf(F, "graph: { title: \"");
2505 fprintf(F, "\" label: \"");
2506 dump_node_opcode(F, b);
2507 fprintf (F, " %ld", get_irn_node_nr(b));
2508 fprintf(F, "\" status:clustered color:lightblue\n");
2510 /* dump the nodes that go into the block */
2511 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2512 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2514 overrule_nodecolor = NULL;
2515 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2518 /* Close the vcg information for the block */
2520 dump_const_node_local(F, b);
2524 eset_destroy(loopnodes);
2525 eset_destroy(extnodes);