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 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 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));
718 if ((get_irp_ip_view_state() == ip_view_valid) && !interprocedural_view) {
719 ir_node *sbl = get_nodes_block(n);
720 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
721 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
722 for (i = 0; i < n_cfgpreds; ++i) {
723 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
724 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
725 get_irg_dump_name(get_irn_irg(cfgpred)));
730 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
733 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
736 entity *ent = get_Sel_entity(n);
739 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
740 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
743 fprintf(F, "<NULL entity>\n");
748 type *tp = get_Call_type(n);
749 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
750 for (i = 0; i < get_method_n_params(tp); ++i)
751 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
752 for (i = 0; i < get_method_n_ress(tp); ++i)
753 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
754 if (Call_has_callees(n)) {
755 fprintf(F, "possible callees: \n");
756 for (i = 0; i < get_Call_n_callees(n); i++) {
757 if (!get_Call_callee(n, i)) {
758 fprintf(F, " %d external method\n", i);
760 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
765 case iro_CallBegin: {
766 ir_node *call = get_CallBegin_call(n);
767 if (Call_has_callees(call)) {
768 fprintf(F, "possible callees: \n");
769 for (i = 0; i < get_Call_n_callees(call); i++) {
770 if (!get_Call_callee(call, i)) {
771 fprintf(F, " %d external method\n", i);
773 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
779 if (!interprocedural_view) {
780 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
781 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
782 for (i = 0; i < get_method_n_ress(tp); ++i)
783 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
787 type *tp = get_Const_type(n);
788 assert(tp != none_type);
789 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
792 switch(get_SymConst_kind(n)) {
793 case symconst_addr_name:
794 fprintf(F, "kind addr_name\n");
796 case symconst_addr_ent:
797 fprintf(F, "kind addr_ent\n");
798 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
800 case symconst_type_tag:
801 fprintf(F, "kind type_tag\n");
804 fprintf(F, "kind size\n");
810 if (interprocedural_view) {
811 fprintf(F, "intra predecessor nodes:\n");
812 for (i = 0; i < get_irn_intra_arity(n); i++) {
813 ir_node *pred = get_irn_intra_n(n, i);
814 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
817 fprintf(F, "inter predecessor nodes:\n");
818 for (i = 0; i < get_irn_inter_arity(n); i++) {
819 ir_node *pred = get_irn_inter_n(n, i);
820 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
821 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
826 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
829 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
835 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
836 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
837 if (get_irn_type(n) != none_type)
838 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
847 bool is_constlike_node(ir_node *n) {
848 ir_op *op = get_irn_op(n);
849 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
853 /* outputs the predecessors of n, that are constants, local. I.e.,
854 generates a copy of the constant predecessors for each node called with. */
855 static void dump_const_node_local(FILE *F, ir_node *n) {
857 if (!get_opt_dump_const_local()) return;
859 /* Use visited flag to avoid outputting nodes twice.
860 initialize it first. */
861 for (i = 0; i < get_irn_arity(n); i++) {
862 ir_node *con = get_irn_n(n, i);
863 if (is_constlike_node(con)) {
864 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
868 for (i = 0; i < get_irn_arity(n); i++) {
869 ir_node *con = get_irn_n(n, i);
870 if (is_constlike_node(con) && irn_not_visited(con)) {
873 mark_irn_visited(con);
874 /* Generate a new name for the node by appending the names of
876 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
877 fprintf(F, " label: \"");
878 bad |= dump_node_opcode(F, con);
879 bad |= dump_node_mode(F, con);
880 bad |= dump_node_typeinfo(F, con);
882 bad |= dump_node_nodeattr(F, con);
883 fprintf(F, " %ld", get_irn_node_nr(con));
885 bad |= dump_node_info(F, con);
886 dump_node_vcgattr(F, con, bad);
892 static void INLINE print_node_error(FILE *F, const char *p)
897 fprintf (F, " info2: \"%s\"", p);
900 static void dump_node(FILE *F, ir_node *n)
905 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
907 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
909 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
910 bad |= dump_node_opcode(F, n);
911 bad |= dump_node_mode(F, n);
912 bad |= dump_node_typeinfo(F, n);
914 bad |= dump_node_nodeattr(F, n);
915 fprintf(F, " %ld", get_irn_node_nr(n));
917 bad |= dump_node_info(F, n);
918 print_node_error(F, p);
919 dump_node_vcgattr(F, n, bad);
921 dump_const_node_local(F, n);
928 /* dump the edge to the block this node belongs to */
930 dump_ir_block_edge(FILE *F, ir_node *n) {
931 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
932 if (is_no_Block(n)) {
933 ir_node *block = get_nodes_block(n);
935 fprintf (F, "edge: { sourcename: \"");
937 fprintf (F, "\" targetname: ");
938 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
939 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
944 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
945 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
946 fprintf (F, INTRA_DATA_EDGE_ATTR);
948 fprintf (F, INTER_DATA_EDGE_ATTR);
952 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
953 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
954 fprintf (F, INTRA_MEM_EDGE_ATTR);
956 fprintf (F, INTER_MEM_EDGE_ATTR);
960 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
963 if (dump_backedge_information_flag && is_backedge(from, to))
964 fprintf (F, BACK_EDGE_ATTR);
966 switch (get_irn_opcode(from)) {
968 fprintf (F, CF_EDGE_ATTR);
970 case iro_Start: break;
973 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
974 fprintf (F, CF_EDGE_ATTR);
975 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
976 fprintf (F, INTER_MEM_EDGE_ATTR);
984 print_data_edge_vcgattr(F, from, to);
989 print_mem_edge_vcgattr(F, from, to);
991 print_data_edge_vcgattr(F, from, to);
995 print_data_edge_vcgattr(F, from, to);
1000 print_mem_edge_vcgattr(F, from, to);
1002 print_data_edge_vcgattr(F, from, to);
1009 print_data_edge_vcgattr(F, from, to);
1016 print_mem_edge_vcgattr(F, from, to);
1018 print_data_edge_vcgattr(F, from, to);
1030 print_data_edge_vcgattr(F, from, to);
1033 if (get_irn_modecode(from) == irm_M)
1034 fprintf (F, INTER_MEM_EDGE_ATTR);
1036 print_data_edge_vcgattr(F, from, to);
1043 print_mem_edge_vcgattr(F, from, to);
1045 print_data_edge_vcgattr(F, from, to);
1048 print_mem_edge_vcgattr(F, from, to);
1050 case iro_Tuple: break;
1053 switch (get_irn_modecode(from)) {
1055 fprintf (F, CF_EDGE_ATTR);
1058 fprintf (F, INTER_MEM_EDGE_ATTR);
1061 print_data_edge_vcgattr(F, from, to);
1065 case iro_Bad: break;
1066 case iro_Unknown: break;
1068 switch (get_irn_modecode(from)) {
1070 fprintf (F, INTRA_MEM_EDGE_ATTR);
1073 fprintf (F, CF_EDGE_ATTR);
1076 print_data_edge_vcgattr(F, from, to);
1084 /* dump edges to our inputs */
1086 dump_ir_data_edges(FILE *F, ir_node *n) {
1087 int i, visited = get_irn_visited(n);
1089 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1092 for (i = 0; i < get_irn_arity(n); i++) {
1093 ir_node * pred = get_irn_n(n, i);
1096 if ((interprocedural_view && get_irn_visited(pred) < visited))
1097 continue; /* pred not dumped */
1099 if (dump_backedge_information_flag && is_backedge(n, i))
1100 fprintf (F, "backedge: {sourcename: \"");
1102 fprintf (F, "edge: {sourcename: \"");
1104 fprintf (F, "\" targetname: ");
1105 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1106 PRINT_CONSTID(n, pred);
1108 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1110 fprintf (F, " label: \"%d\" ", i);
1111 print_edge_vcgattr(F, n, i);
1116 /** Dumps a node and its edges but not the block edge
1119 dump_node_wo_blockedge (ir_node *n, void *env) {
1122 dump_ir_data_edges(F, n);
1125 /** Dumps a node and its edges.
1128 dump_whole_node (ir_node *n, void *env) {
1130 dump_node_wo_blockedge(n, env);
1131 if (!node_floats(n)) dump_ir_block_edge(F, n);
1135 dump_const_node(ir_node *n, void *env) {
1136 if (is_Block(n)) return;
1137 dump_node_wo_blockedge(n, env);
1140 /***********************************************************************/
1141 /* the following routines dump the nodes/irgs bracketed to graphs. */
1142 /***********************************************************************/
1144 /** Dumps a constant expression as entity initializer, array bound ...
1146 static void dump_const_expression(FILE *F, ir_node *value) {
1147 ir_graph *rem = current_ir_graph;
1148 int rem_dump_const_local = dump_const_local;
1149 dump_const_local = 0;
1150 current_ir_graph = get_const_code_irg();
1151 irg_walk(value, dump_const_node, NULL, F);
1152 /* Decrease visited flag so that we walk with the same flag for the next
1153 expresssion. This guarantees that we don't dump the same node twice,
1154 as for const expressions cse is performed to save memory. */
1155 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1156 current_ir_graph = rem;
1157 dump_const_local = rem_dump_const_local;
1160 /** Dump a block as graph containing its nodes.
1162 * Expects to find nodes belonging to the block as list in its
1164 * Dumps the edges of all nodes including itself. */
1166 dump_whole_block(FILE *F, ir_node *block) {
1168 assert(is_Block(block));
1170 fprintf(F, "graph: { title: \"");
1171 PRINT_NODEID(block);
1172 fprintf(F, "\" label: \"");
1173 dump_node_opcode(F, block);
1174 fprintf (F, " %ld", get_irn_node_nr(block));
1176 if (get_opt_dump_abstvals())
1177 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1179 fprintf(F, "\" status:clustered color:%s \n",
1180 get_Block_matured(block) ? "yellow" : "red");
1182 /* dump the blocks edges */
1183 dump_ir_data_edges(F, block);
1185 /* dump the nodes that go into the block */
1186 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1188 dump_ir_data_edges(F, node);
1191 /* Close the vcg information for the block */
1193 dump_const_node_local(F, block);
1195 dump_chi_term(F, block);
1200 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1201 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1203 dump_block_graph(FILE *F, ir_graph *irg) {
1205 ir_graph *rem = current_ir_graph;
1206 ir_node **arr = ird_get_irg_link(irg);
1207 current_ir_graph = irg;
1209 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1210 ir_node * node = arr[i];
1211 if (is_Block(node)) {
1212 /* Dumps the block and all the nodes in the block, which are to
1213 be found in Block->link. */
1214 dump_whole_block(F, node);
1216 /* Nodes that are not in a Block. */
1218 dump_ir_data_edges(F, node);
1222 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1223 dump_loop_nodes_into_graph(F, irg);
1225 current_ir_graph = rem;
1228 /** Dumps an irg as a graph.
1229 * If interprocedural view edges can point to nodes out of this graph.
1231 static void dump_graph(FILE *F, ir_graph *irg) {
1233 fprintf(F, "graph: { title: \"");
1235 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1236 get_ent_dump_name(get_irg_entity(irg)));
1238 dump_block_graph(F, irg);
1240 /* Close the vcg information for the irg */
1241 fprintf(F, "}\n\n");
1244 /*******************************************************************/
1245 /* Basic type and entity nodes and edges. */
1246 /*******************************************************************/
1248 /* dumps the edges between nodes and their type or entity attributes. */
1249 static void dump_node2type_edges(ir_node *n, void *env)
1254 switch (get_irn_opcode(n)) {
1256 /* @@@ some consts have an entity */
1259 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1260 || (get_SymConst_kind(n) ==symconst_size))
1262 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1266 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1269 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1272 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1275 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1278 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1286 static int print_type_info(FILE *F, type *tp) {
1289 if (get_type_state(tp) == layout_undefined) {
1290 fprintf(F, "state: layout_undefined\n");
1292 fprintf(F, "state: layout_fixed,\n");
1294 if (get_type_mode(tp))
1295 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1296 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1301 static void print_typespecific_info(FILE *F, type *tp) {
1302 switch (get_type_tpop_code(tp)) {
1305 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1312 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1313 fprintf(F, "params: %d\n", get_method_n_params(tp));
1314 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1322 case tpo_enumeration:
1336 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1337 switch (get_type_tpop_code(tp)) {
1340 if (peculiarity_existent == get_class_peculiarity(tp))
1341 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1343 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1347 fprintf (F, " " TYPE_METH_NODE_ATTR);
1358 case tpo_enumeration:
1371 static int print_type_node(FILE *F, type *tp)
1375 fprintf (F, "node: {title: ");
1377 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1378 fprintf (F, " info1: \"");
1379 bad |= print_type_info(F, tp);
1380 print_typespecific_info(F, tp);
1382 print_typespecific_vcgattr(F, tp);
1388 #define X(a) case a: fprintf(F, #a); break
1389 void dump_entity_node(FILE *F, entity *ent, int color)
1391 fprintf (F, "node: {title: \"");
1392 PRINT_ENTID(ent); fprintf(F, "\"");
1393 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1394 fprintf (F, "label: ");
1395 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1397 fprintf(F, "color: %d", color);
1399 fprintf (F, ENTITY_NODE_ATTR);
1400 fprintf (F, "\n info1: \"");
1402 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1404 fprintf(F, "\"\n}\n");
1408 static void dump_enum_item(FILE *F, type *tp, int pos)
1411 ident *id = get_enumeration_nameid(tp, pos);
1412 tarval *tv = get_enumeration_enum(tp, pos);
1414 tarval_snprintf(buf, sizeof(buf), tv);
1415 fprintf (F, "node: {title: \"");
1416 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1417 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1418 fprintf (F, "label: ");
1419 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1420 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1423 /* dumps a type or entity and it's edges. */
1425 dump_type_info(type_or_ent *tore, void *env) {
1427 int i = 0; /* to shutup gcc */
1429 /* dump this type or entity */
1431 switch (get_kind(tore)) {
1434 entity *ent = (entity *)tore;
1437 dump_entity_node(F, ent, 0);
1439 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1440 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1441 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1442 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1443 if(is_class_type(get_entity_owner(ent))) {
1444 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1445 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1447 /* attached subgraphs */
1448 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1449 if (is_atomic_entity(ent)) {
1450 value = get_atomic_ent_value(ent);
1452 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1453 /* DDMN(value); $$$ */
1454 dump_const_expression(F, value);
1457 if (is_compound_entity(ent)) {
1458 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1459 value = get_compound_ent_value(ent, i);
1461 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1462 dump_const_expression(F, value);
1463 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1465 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1466 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1467 get_compound_ent_value_member(ent, i), i);
1476 type *tp = (type *)tore;
1477 print_type_node(F, tp);
1478 /* and now the edges */
1479 switch (get_type_tpop_code(tp)) {
1482 for (i=0; i < get_class_n_supertypes(tp); i++)
1483 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1484 for (i=0; i < get_class_n_members(tp); i++)
1485 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1489 for (i=0; i < get_struct_n_members(tp); i++)
1490 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1494 for (i = 0; i < get_method_n_params(tp); i++)
1495 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1496 for (i = 0; i < get_method_n_ress(tp); i++)
1497 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1501 for (i = 0; i < get_union_n_members(tp); i++)
1502 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1506 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1507 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1508 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1509 ir_node *upper = get_array_upper_bound(tp, i);
1510 ir_node *lower = get_array_lower_bound(tp, i);
1511 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1512 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1513 dump_const_expression(F, upper);
1514 dump_const_expression(F, lower);
1518 case tpo_enumeration:
1520 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1521 dump_enum_item(F, tp, i);
1522 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1527 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1535 break; /* case k_type */
1538 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1540 } /* switch kind_or_entity */
1543 typedef struct _h_env {
1548 /** For dumping class hierarchies.
1549 * Dumps a class type node and a superclass edge.
1550 * If env->dump_ent dumps entities of classes and overwrites edges.
1553 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1556 int i = 0; /* to shutup gcc */
1558 /* dump this type or entity */
1559 switch (get_kind(tore)) {
1561 entity *ent = (entity *)tore;
1562 if (get_entity_owner(ent) == get_glob_type()) break;
1563 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1564 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1566 dump_entity_node(F, ent, 0);
1568 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1569 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1570 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1572 } break; /* case k_entity */
1575 type *tp = (type *)tore;
1576 if (tp == get_glob_type()) break;
1577 switch (get_type_tpop_code(tp)) {
1579 print_type_node(F, tp);
1580 /* and now the edges */
1581 for (i=0; i < get_class_n_supertypes(tp); i++)
1583 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1589 break; /* case k_type */
1592 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1594 } /* switch kind_or_entity */
1597 /*******************************************************************/
1598 /* dump analysis information that is expressed in graph terms. */
1599 /*******************************************************************/
1601 /* dump out edges */
1603 dump_out_edge(ir_node *n, void *env) {
1606 for (i = 0; i < get_irn_n_outs(n); i++) {
1607 assert(get_irn_out(n, i));
1608 fprintf (F, "edge: {sourcename: \"");
1610 fprintf (F, "\" targetname: \"");
1611 PRINT_NODEID(get_irn_out(n, i));
1612 fprintf (F, "\" color: red linestyle: dashed");
1618 dump_loop_label(FILE *F, ir_loop *loop) {
1619 fprintf (F, "loop %d, %d sons, %d nodes",
1620 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1623 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1624 fprintf (F, " info1: \"");
1625 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1626 #if DEBUG_libfirm /* GL @@@ debug analyses */
1627 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1633 dump_loop_node(FILE *F, ir_loop *loop) {
1634 fprintf (F, "node: {title: \"");
1636 fprintf (F, "\" label: \"");
1637 dump_loop_label(F, loop);
1639 dump_loop_info(F, loop);
1645 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1647 fprintf (F, "edge: {sourcename: \"");
1649 fprintf (F, "\" targetname: \"");
1650 PRINT_NODEID(get_loop_node(loop, i));
1651 fprintf (F, "\" color: green");
1656 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1658 fprintf (F, "edge: {sourcename: \"");
1660 fprintf (F, "\" targetname: \"");
1661 PRINT_LOOPID(get_loop_son(loop, i));
1662 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1663 get_loop_element_pos(loop, get_loop_son(loop, i)));
1667 void dump_loops(FILE *F, ir_loop *loop) {
1669 /* dump this loop node */
1670 dump_loop_node(F, loop);
1672 /* dump edges to nodes in loop -- only if it is a real loop */
1673 if (get_loop_depth(loop) != 0) {
1674 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1675 dump_loop_node_edge(F, loop, i);
1678 for (i = 0; i < get_loop_n_sons(loop); i++) {
1679 dump_loops(F, get_loop_son(loop, i));
1680 dump_loop_son_edge(F, loop, i);
1685 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1686 ir_graph *rem = current_ir_graph;
1687 current_ir_graph = irg;
1689 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1691 current_ir_graph = rem;
1696 * dumps the VCG header
1699 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1708 if (!orientation) orientation = "bottom_to_top";
1712 "graph: { title: \"ir graph of %s\"\n"
1713 "display_edge_labels: %s\n"
1714 "layoutalgorithm: mindepth\n"
1715 "manhattan_edges: yes\n"
1716 "port_sharing: no\n"
1718 "classname 1: \"intrablock Data\"\n"
1719 "classname 16: \"interblock Data\"\n"
1720 "classname 2: \"Block\"\n"
1721 "classname 13: \"Control Flow\"\n"
1722 "classname 14: \"intrablock Memory\"\n"
1723 "classname 17: \"interblock Memory\"\n"
1724 "classname 15: \"Dominators\"\n"
1725 "classname 3: \"Entity type\"\n"
1726 "classname 4: \"Entity owner\"\n"
1727 "classname 5: \"Method Param\"\n"
1728 "classname 6: \"Method Res\"\n"
1729 "classname 7: \"Super\"\n"
1730 "classname 8: \"Union\"\n"
1731 "classname 9: \"Points-to\"\n"
1732 "classname 10: \"Array Element Type\"\n"
1733 "classname 11: \"Overwrites\"\n"
1734 "classname 12: \"Member\"\n"
1735 "infoname 1: \"Attribute\"\n"
1736 "infoname 2: \"Verification errors\"\n",
1737 name, label, orientation);
1739 /* don't use all, the range is too whith/black. */
1743 "colorentry 100: 0 0 0\n"
1744 "colorentry 101: 20 0 0\n"
1745 "colorentry 102: 40 0 0\n"
1746 "colorentry 103: 60 0 0\n"
1747 "colorentry 104: 80 0 0\n"
1748 "colorentry 105: 100 0 0\n"
1749 "colorentry 106: 120 0 0\n"
1750 "colorentry 107: 140 0 0\n"
1751 "colorentry 108: 150 0 0\n"
1752 "colorentry 109: 180 0 0\n"
1753 "colorentry 110: 200 0 0\n"
1754 "colorentry 111: 220 0 0\n"
1755 "colorentry 112: 240 0 0\n"
1756 "colorentry 113: 255 0 0\n"
1757 "colorentry 113: 255 20 20\n"
1758 "colorentry 114: 255 40 40\n"
1759 "colorentry 115: 255 60 60\n"
1760 "colorentry 116: 255 80 80\n"
1761 "colorentry 117: 255 100 100\n"
1762 "colorentry 118: 255 120 120\n"
1763 "colorentry 119: 255 140 140\n"
1764 "colorentry 120: 255 150 150\n"
1765 "colorentry 121: 255 180 180\n"
1766 "colorentry 122: 255 200 200\n"
1767 "colorentry 123: 255 220 220\n"
1768 "colorentry 124: 255 240 240\n"
1769 "colorentry 125: 255 250 250\n"
1772 fprintf (F, "\n"); /* a separator */
1778 * @param irg The graph to be dumped
1779 * @param suffix1 first filename suffix
1780 * @param suffix2 second filename suffix
1782 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1784 const char *nm = get_irg_dump_name(irg);
1785 int len = strlen(nm), i, j;
1786 char *fname; /* filename to put the vcg information in */
1788 if (!suffix1) suffix1 = "";
1789 if (!suffix2) suffix2 = "";
1791 /* open file for vcg graph */
1792 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1794 /* strncpy (fname, nm, len); */ /* copy the filename */
1796 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1798 fname[j] = '@'; j++; fname[j] = '1'; j++;
1799 } else if (nm[i] == '@') {
1800 fname[j] = '@'; j++; fname[j] = '2'; j++;
1802 fname[j] = nm[i]; j++;
1806 strcat (fname, suffix1); /* append file suffix */
1807 strcat (fname, suffix2); /* append file suffix */
1808 strcat (fname, ".vcg"); /* append the .vcg suffix */
1809 F = fopen (fname, "w"); /* open file for writing */
1811 panic("cannot open %s for writing (%m)", fname); /* not reached */
1821 * @param irg The graph to be dumped
1822 * @param suffix filename suffix
1824 static FILE *vcg_open_name (const char *name, const char *suffix) {
1826 char *fname; /* filename to put the vcg information in */
1827 int i, j, len = strlen(name);
1829 if (!suffix) suffix = "";
1831 /** open file for vcg graph */
1832 fname = malloc (len * 2 + 5 + strlen(suffix));
1833 /* strcpy (fname, name);*/ /* copy the filename */
1835 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1836 if (name[i] == '/') {
1837 fname[j] = '@'; j++; fname[j] = '1'; j++;
1838 } else if (name[i] == '@') {
1839 fname[j] = '@'; j++; fname[j] = '2'; j++;
1841 fname[j] = name[i]; j++;
1845 strcat (fname, suffix);
1846 strcat (fname, ".vcg"); /* append the .vcg suffix */
1847 F = fopen (fname, "w"); /* open file for writing */
1849 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1857 * Dumps the vcg file footer
1859 static INLINE void dump_vcg_footer (FILE *F) {
1864 * close the vcg file
1867 vcg_close (FILE *F) {
1868 dump_vcg_footer(F); /* print footer */
1869 fclose (F); /* close vcg file */
1872 /************************************************************************/
1873 /************************************************************************/
1874 /* Routines that dump all or parts of the firm representation to a file */
1875 /************************************************************************/
1876 /************************************************************************/
1878 /************************************************************************/
1879 /* Dump ir graphs, differnt formats and additional information. */
1880 /************************************************************************/
1882 /** Routine to dump a graph, blocks as conventional nodes.
1885 dump_ir_graph (ir_graph *irg, const char *suffix )
1890 rem = current_ir_graph;
1892 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1893 current_ir_graph = irg;
1894 if (interprocedural_view) suffix1 = "-pure-ip";
1895 else suffix1 = "-pure";
1896 f = vcg_open(irg, suffix, suffix1);
1897 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1899 /* walk over the graph */
1900 /* dump_whole_node must be called in post visiting predecessors */
1901 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1903 /* dump the out edges in a separate walk */
1904 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1905 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1910 current_ir_graph = rem;
1915 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1921 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1924 if (interprocedural_view) suffix1 = "-ip";
1926 f = vcg_open(irg, suffix, suffix1);
1927 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1929 construct_block_lists(irg);
1931 for (i = 0; i < get_irp_n_irgs(); i++) {
1932 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1934 dump_graph(f, get_irp_irg(i));
1942 /** dumps a graph with type information
1945 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1948 ir_graph *rem = current_ir_graph;
1951 /* if a filter is set, dump only the irg's that match the filter */
1952 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1955 current_ir_graph = irg;
1957 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1958 else suffix1 = "-pure-wtypes";
1959 f = vcg_open(irg,suffix, suffix1);
1960 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1962 /* dump common ir graph */
1963 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1964 /* dump type info */
1965 type_walk_irg(irg, dump_type_info, NULL, f);
1966 inc_irg_visited(get_const_code_irg());
1967 /* dump edges from graph to type info */
1968 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1971 current_ir_graph = rem;
1975 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1980 ir_graph *rem = current_ir_graph;
1982 /* if a filter is set, dump only the irg's that match the filter */
1983 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1986 if (interprocedural_view) suffix1 = "-wtypes-ip";
1987 else suffix1 = "-wtypes";
1988 f = vcg_open(irg, suffix, suffix1);
1989 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1991 /* dump common blocked ir graph */
1992 construct_block_lists(irg);
1994 for (i = 0; i < get_irp_n_irgs(); i++) {
1995 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1997 dump_graph(f, get_irp_irg(i));
2002 /* dump type info */
2003 current_ir_graph = irg;
2004 type_walk_irg(irg, dump_type_info, NULL, f);
2005 inc_irg_visited(get_const_code_irg());
2007 /* dump edges from graph to type info */
2008 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2010 current_ir_graph = rem;
2014 /*---------------------------------------------------------------------*/
2015 /* The following routines dump a control flow graph. */
2016 /*---------------------------------------------------------------------*/
2019 dump_block_to_cfg(ir_node *block, void *env) {
2024 if (is_Block(block)) {
2025 /* This is a block. Dump a node for the block. */
2026 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2027 fprintf (F, "\" label: \"");
2028 if (block == get_irg_start_block(get_irn_irg(block)))
2029 fprintf(F, "Start ");
2030 if (block == get_irg_end_block(get_irn_irg(block)))
2033 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2034 PRINT_NODEID(block);
2036 fprintf(F, "info1:\"");
2037 if (dump_dominator_information_flag)
2038 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2040 /* show arity and possible Bad predecessors of the block */
2041 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2042 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2043 ir_node *pred = get_Block_cfgpred(block, i);
2046 fprintf(F, "Bad pred at pos: ");
2047 fprintf(F, "%d ", i);
2054 fprintf (F, "\""); /* closing quote of info */
2056 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2057 (block == get_irg_end_block(get_irn_irg(block))) )
2058 fprintf(F, " color:blue ");
2060 fprintf(F, " color:yellow ");
2063 /* Dump the edges */
2064 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2065 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2066 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2067 fprintf (F, "edge: { sourcename: \"");
2068 PRINT_NODEID(block);
2069 fprintf (F, "\" targetname: \"");
2071 fprintf (F, "\"}\n");
2074 /* Dump dominator edge */
2075 if (dump_dominator_information_flag && get_Block_idom(block)) {
2076 pred = get_Block_idom(block);
2077 fprintf (F, "edge: { sourcename: \"");
2078 PRINT_NODEID(block);
2079 fprintf (F, "\" targetname: \"");
2081 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2087 dump_cfg (ir_graph *irg, const char *suffix)
2090 ir_graph *rem = current_ir_graph;
2091 int ddif = dump_dominator_information_flag;
2092 int ipv = interprocedural_view;
2094 /* if a filter is set, dump only the irg's that match the filter */
2095 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2098 current_ir_graph = irg;
2100 f = vcg_open(irg, suffix, "-cfg");
2101 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2103 if (interprocedural_view) {
2104 printf("Warning: dumping cfg not in interprocedural view!\n");
2105 interprocedural_view = 0;
2108 if (get_irg_dom_state(irg) != dom_consistent)
2109 dump_dominator_information_flag = 0;
2111 /* walk over the blocks in the graph */
2112 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2113 dump_node(f, get_irg_bad(irg));
2115 dump_dominator_information_flag = ddif;
2116 interprocedural_view = ipv;
2118 current_ir_graph = rem;
2121 static int weight_overall(int rec, int loop) {
2122 return 2*rec + loop;
2125 static int compute_color (int my, int max) {
2130 /* if small, scale to the full color range. */
2132 my = my * (n_colors/max);
2134 int step = 1 + (max / n_colors);
2138 return base_color + n_colors - color;
2141 static int get_entity_color(entity *ent) {
2142 assert(get_entity_irg(ent));
2143 ir_graph *irg = get_entity_irg(ent);
2145 int rec_depth = get_irg_recursion_depth(irg);
2146 int loop_depth = get_irg_loop_depth(irg);
2147 int overall_depth = weight_overall(rec_depth, loop_depth);
2149 int max_rec_depth = irp->max_callgraph_recursion_depth;
2150 int max_loop_depth = irp->max_callgraph_loop_depth;
2151 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2153 int my_rec_color = compute_color(rec_depth, max_rec_depth);
2154 int my_loop_color = compute_color(loop_depth, max_loop_depth);
2155 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2157 return my_overall_color;
2160 void dump_callgraph(const char *suffix) {
2162 int i, n_irgs = get_irp_n_irgs();
2163 int rem = edge_label;
2165 //ident *prefix = new_id_from_str("java/");
2167 F = vcg_open_name("Callgraph", suffix);
2168 dump_vcg_header(F, "Callgraph", NULL);
2170 for (i = 0; i < n_irgs; ++i) {
2171 ir_graph *irg = get_irp_irg(i);
2172 entity *ent = get_irg_entity(irg);
2173 int j, n_callees = get_irg_n_callees(irg);
2175 /* Do not dump runtime system. */
2176 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2178 dump_entity_node(F, ent, get_entity_color(ent));
2179 for (j = 0; j < n_callees; ++j) {
2180 entity *c = get_irg_entity(get_irg_callee(irg, j));
2181 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2182 int be = is_irg_callee_backedge(irg, j);
2185 "label:\"recursion %d\" color: %d" :
2186 "label:\"calls %d\" color: %d";
2187 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2195 /* Dump all irgs in interprocedural view to a single file. */
2196 void dump_all_cg_block_graph(const char *suffix) {
2199 int rem_view = interprocedural_view;
2200 interprocedural_view = 1;
2202 f = vcg_open_name("All_graphs", suffix);
2203 dump_vcg_header(f, "All_graphs", NULL);
2205 /* collect nodes in all irgs reachable in call graph*/
2206 for (i = 0; i < get_irp_n_irgs(); i++)
2207 ird_set_irg_link(get_irp_irg(i), NULL);
2209 cg_walk(clear_link, collect_node, NULL);
2211 /* dump all graphs */
2212 for (i = 0; i < get_irp_n_irgs(); i++) {
2213 current_ir_graph = get_irp_irg(i);
2214 assert(ird_get_irg_link(current_ir_graph));
2215 dump_graph(f, current_ir_graph);
2216 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2220 interprocedural_view = rem_view;
2223 /***********************************************************************/
2224 /* the following routines dumps type information without any ir nodes. */
2225 /***********************************************************************/
2228 dump_type_graph (ir_graph *irg, const char *suffix)
2232 rem = current_ir_graph;
2234 /* if a filter is set, dump only the irg's that match the filter */
2235 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2237 current_ir_graph = irg;
2239 f = vcg_open(irg, suffix, "-type");
2240 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2242 /* walk over the blocks in the graph */
2243 type_walk_irg(irg, dump_type_info, NULL, f);
2244 /* The walker for the const code can be called several times for the
2245 same (sub) experssion. So that no nodes are dumped several times
2246 we decrease the visited flag of the corresponding graph after each
2247 walk. So now increase it finally. */
2248 inc_irg_visited(get_const_code_irg());
2251 current_ir_graph = rem;
2255 dump_all_types (const char *suffix)
2257 FILE *f = vcg_open_name("All_types", suffix);
2258 dump_vcg_header(f, "All_types", NULL);
2259 type_walk(dump_type_info, NULL, f);
2260 inc_irg_visited(get_const_code_irg());
2265 dump_class_hierarchy (bool entities, const char *suffix)
2267 FILE *f = vcg_open_name("class_hierarchy", suffix);
2271 dump_vcg_header(f, "class_hierarchy", NULL);
2276 type_walk(dump_class_hierarchy_node, NULL, &env);
2280 /***********************************************************************/
2281 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2283 /* dump_ir_block_graph */
2285 /* dump_type_graph */
2286 /* dump_ir_graph_w_types */
2287 /***********************************************************************/
2289 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2290 int i, n_irgs = get_irp_n_irgs();
2291 for (i = 0; i < n_irgs; ++i) {
2292 dmp_grph(get_irp_irg(i), suffix);
2297 /**********************************************************************************
2298 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2299 * packed together in one subgraph/box *
2300 **********************************************************************************/
2302 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2303 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2305 ir_loop *son = NULL;
2307 /* Dump a new loop node. */
2308 dump_loop_node(F, loop);
2310 /* Dump the loop elements. */
2312 for(i = 0; i < get_loop_n_elements(loop); i++) {
2313 le = get_loop_element(loop, i);
2315 if (get_kind(son) == k_ir_loop) {
2317 /* We are a loop son -> Recurse */
2319 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2320 fprintf(F, "\" }\n");
2321 fprintf (F, "edge: {sourcename: \"");
2323 fprintf (F, "\" targetname: \"");
2325 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2326 loop_node_started = 0;
2328 dump_loop_son_edge(F, loop, son_number++);
2329 dump_loops_standalone(F, son);
2330 } else if (get_kind(son) == k_ir_node) {
2331 /* We are a loop node -> Collect firm nodes */
2333 ir_node *n = le.node;
2336 if (!loop_node_started) {
2337 /* Start a new node which contains all firm nodes of the current loop */
2338 fprintf (F, "node: { title: \"");
2340 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2341 loop_node_started = 1;
2347 bad |= dump_node_opcode(F, n);
2348 bad |= dump_node_mode(F, n);
2349 bad |= dump_node_typeinfo(F, n);
2351 bad |= dump_node_nodeattr(F, n);
2352 fprintf (F, " %ld", get_irn_node_nr(n));
2353 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2354 } else { /* for callgraph loop tree */
2355 assert(get_kind(son) == k_ir_graph);
2356 /* We are a loop node -> Collect firm graphs */
2357 ir_graph *n = (ir_graph *)le.node;
2358 if (!loop_node_started) {
2359 /* Start a new node which contains all firm nodes of the current loop */
2360 fprintf (F, "node: { title: \"");
2362 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2363 loop_node_started = 1;
2368 fprintf (F, " %s", get_irg_dump_name(n));
2369 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2373 if (loop_node_started) {
2374 fprintf(F, "\" }\n");
2375 fprintf (F, "edge: {sourcename: \"");
2377 fprintf (F, "\" targetname: \"");
2379 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2380 loop_node_started = 0;
2384 void dump_loop_tree(ir_graph *irg, const char *suffix)
2387 ir_graph *rem = current_ir_graph;
2388 int el_rem = edge_label;
2391 /* if a filter is set, dump only the irg's that match the filter */
2392 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2395 current_ir_graph = irg;
2397 f = vcg_open(irg, suffix, "-looptree");
2398 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2400 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2404 edge_label = el_rem;
2405 current_ir_graph = rem;
2408 void dump_callgraph_loop_tree(const char *suffix) {
2410 F = vcg_open_name("Callgraph_looptree", suffix);
2411 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2412 dump_loops_standalone(F, irp->outermost_cg_loop);
2417 /*******************************************************************************/
2418 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2419 /*******************************************************************************/
2421 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2422 int i, son_number = 0, node_number = 0;
2424 if (dump_loop_information_flag) dump_loop_node(F, loop);
2426 for (i = 0; i < get_loop_n_elements(loop); i++) {
2427 loop_element le = get_loop_element(loop, i);
2428 if (*(le.kind) == k_ir_loop) {
2429 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2431 collect_nodeloop(F, le.son, loopnodes);
2433 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2434 eset_insert(loopnodes, le.node);
2439 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2442 for(i = 0; i < get_loop_n_elements(loop); i++) {
2443 loop_element le = get_loop_element(loop, i);
2444 if (*(le.kind) == k_ir_loop) {
2446 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2448 if (is_Block(le.node)) start = 0; else start = -1;
2449 for (j = start; j < get_irn_arity(le.node); j++) {
2450 ir_node *pred = get_irn_n(le.node, j);
2451 if (!eset_contains(loopnodes, pred)) {
2452 eset_insert(extnodes, pred);
2453 if (!is_Block(pred)) {
2454 pred = get_nodes_block(pred);
2455 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2463 void dump_loop(ir_loop *l, const char *suffix) {
2466 eset *loopnodes = eset_create();
2467 eset *extnodes = eset_create();
2470 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2471 F = vcg_open_name (name, suffix);
2472 dump_vcg_header(F, name, NULL);
2474 /* collect all nodes to dump */
2475 collect_nodeloop(F, l, loopnodes);
2476 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2478 /* build block lists */
2479 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2480 set_irn_link(n, NULL);
2481 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2482 set_irn_link(n, NULL);
2483 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2485 b = get_nodes_block(n);
2486 set_irn_link(n, get_irn_link(b));
2489 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2491 b = get_nodes_block(n);
2492 set_irn_link(n, get_irn_link(b));
2496 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2498 fprintf(F, "graph: { title: \"");
2500 fprintf(F, "\" label: \"");
2501 dump_node_opcode(F, b);
2502 fprintf (F, " %ld", get_irn_node_nr(b));
2503 fprintf(F, "\" status:clustered color:yellow\n");
2505 /* dump the blocks edges */
2506 dump_ir_data_edges(F, b);
2508 /* dump the nodes that go into the block */
2509 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2510 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2512 overrule_nodecolor = NULL;
2513 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2516 /* Close the vcg information for the block */
2518 dump_const_node_local(F, b);
2521 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2523 fprintf(F, "graph: { title: \"");
2525 fprintf(F, "\" label: \"");
2526 dump_node_opcode(F, b);
2527 fprintf (F, " %ld", get_irn_node_nr(b));
2528 fprintf(F, "\" status:clustered color:lightblue\n");
2530 /* dump the nodes that go into the block */
2531 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2532 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2534 overrule_nodecolor = NULL;
2535 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2538 /* Close the vcg information for the block */
2540 dump_const_node_local(F, b);
2544 eset_destroy(loopnodes);
2545 eset_destroy(extnodes);