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_irn_pinned(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)
538 opcode iro = get_irn_opcode(n);
550 ir_mode *mode = get_irn_mode(n);
552 if (mode && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
553 (mode != mode_T || iro == iro_Proj))
554 fprintf(F, "%s", get_mode_name_ex(mode, &bad));
561 static int dump_node_typeinfo(FILE *F, ir_node *n) {
564 if (opt_dump_analysed_type_info) {
565 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
566 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
567 type *tp = get_irn_type(n);
569 fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
578 dump_node_nodeattr(FILE *F, ir_node *n)
582 switch (get_irn_opcode(n)) {
584 if (false && interprocedural_view) {
585 fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
589 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
590 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
592 fprintf (F, "%ld", get_Proj_proj(n));
596 fprintf (F, "%ld", get_Filter_proj(n));
599 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
602 fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
605 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
615 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
618 fprintf(F, "color: red");
621 switch (get_irn_opcode(n)) {
628 fprintf (F, "color: blue");
631 fprintf (F, "color: lightyellow");
634 fprintf (F, "color: green");
640 fprintf (F, "color: yellow");
643 PRINT_DEFAULT_NODE_ATTR;
646 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
649 static INLINE int dump_node_info(FILE *F, ir_node *n)
655 fprintf (F, " info1: \"");
656 if (opt_dump_pointer_values_to_info)
657 fprintf (F, "addr: %p \n", (void *)n);
658 fprintf (F, "mode: %s\n", get_mode_name(get_irn_mode(n)));
659 fprintf (F, "visited: %ld \n", get_irn_visited(n));
660 irg = get_irn_irg(n);
661 if (irg != get_const_code_irg())
662 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
664 if (get_irn_pinned(n) == op_pin_state_floats &&
665 get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats) {
666 fprintf(F, "node was pinned in ");
667 dump_node_opcode(F, get_nodes_block(n));
668 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
672 /* show all predecessor nodes */
673 fprintf(F, "pred nodes: \n");
676 dump_node_opcode(F, get_nodes_block(n));
677 fprintf(F, " %ld\n", get_irn_node_nr(get_nodes_block(n)));
679 for ( i = 0; i < get_irn_arity(n); ++i) {
680 fprintf(F, " %d: ", i);
681 dump_node_opcode(F, get_irn_n(n, i));
682 fprintf(F, " %ld\n", get_irn_node_nr(get_irn_n(n, i)));
686 fprintf(F, "arity: %d", get_irn_arity(n));
687 if ((get_irn_op(n) == op_Block) ||
688 (get_irn_op(n) == op_Phi) ||
689 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
690 fprintf(F, " backedges:");
692 for (i = 0; i < get_irn_arity(n); i++)
693 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
697 /* Loop node Someone else please tell me what's wrong ...
698 if (get_irn_loop(n)) {
699 ir_loop *loop = get_irn_loop(n);
701 fprintf(F, " in loop %d with depth %d\n",
702 get_loop_loop_nr(loop), get_loop_depth(loop));
707 switch (get_irn_opcode(n)) {
709 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
710 fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
711 for (i = 0; i < get_method_n_params(tp); ++i)
712 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
713 if ((get_irp_ip_view_state() == ip_view_valid) && !interprocedural_view) {
714 ir_node *sbl = get_nodes_block(n);
715 int i, n_cfgpreds = get_Block_cg_n_cfgpreds(sbl);
716 fprintf(F, "graph has %d interprocedural predecessors:\n", n_cfgpreds);
717 for (i = 0; i < n_cfgpreds; ++i) {
718 ir_node *cfgpred = get_Block_cg_cfgpred(sbl, i);
719 fprintf(F, " %d: Call %ld in graph %s\n", i, get_irn_node_nr(cfgpred),
720 get_irg_dump_name(get_irn_irg(cfgpred)));
725 fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
728 fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
731 entity *ent = get_Sel_entity(n);
734 fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
735 fprintf(F, " from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
738 fprintf(F, "<NULL entity>\n");
743 type *tp = get_Call_type(n);
744 fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
745 if(get_unknown_type() != tp) {
746 for (i = 0; i < get_method_n_params(tp); ++i)
747 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
748 for (i = 0; i < get_method_n_ress(tp); ++i)
749 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
751 if (Call_has_callees(n)) {
752 fprintf(F, "possible callees: \n");
753 for (i = 0; i < get_Call_n_callees(n); i++) {
754 if (!get_Call_callee(n, i)) {
755 fprintf(F, " %d external method\n", i);
757 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
762 case iro_CallBegin: {
763 ir_node *call = get_CallBegin_call(n);
764 if (Call_has_callees(call)) {
765 fprintf(F, "possible callees: \n");
766 for (i = 0; i < get_Call_n_callees(call); i++) {
767 if (!get_Call_callee(call, i)) {
768 fprintf(F, " %d external method\n", i);
770 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
776 if (!interprocedural_view) {
777 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
778 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
779 for (i = 0; i < get_method_n_ress(tp); ++i)
780 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
784 type *tp = get_Const_type(n);
785 assert(tp != none_type);
786 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
789 switch(get_SymConst_kind(n)) {
790 case symconst_addr_name:
791 fprintf(F, "kind addr_name\n");
793 case symconst_addr_ent:
794 fprintf(F, "kind addr_ent\n");
795 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
797 case symconst_type_tag:
798 fprintf(F, "kind type_tag\n");
801 fprintf(F, "kind size\n");
807 if (interprocedural_view) {
808 fprintf(F, "intra predecessor nodes:\n");
809 for (i = 0; i < get_irn_intra_arity(n); i++) {
810 ir_node *pred = get_irn_intra_n(n, i);
811 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
814 fprintf(F, "inter predecessor nodes:\n");
815 for (i = 0; i < get_irn_inter_arity(n); i++) {
816 ir_node *pred = get_irn_inter_n(n, i);
817 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
818 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
823 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
826 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
832 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
833 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
834 if (get_irn_type(n) != none_type)
835 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
844 bool is_constlike_node(ir_node *n) {
845 ir_op *op = get_irn_op(n);
846 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
850 /* outputs the predecessors of n, that are constants, local. I.e.,
851 generates a copy of the constant predecessors for each node called with. */
852 static void dump_const_node_local(FILE *F, ir_node *n) {
854 if (!get_opt_dump_const_local()) return;
856 /* Use visited flag to avoid outputting nodes twice.
857 initialize it first. */
858 for (i = 0; i < get_irn_arity(n); i++) {
859 ir_node *con = get_irn_n(n, i);
860 if (is_constlike_node(con)) {
861 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
865 for (i = 0; i < get_irn_arity(n); i++) {
866 ir_node *con = get_irn_n(n, i);
867 if (is_constlike_node(con) && irn_not_visited(con)) {
870 mark_irn_visited(con);
871 /* Generate a new name for the node by appending the names of
873 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
874 fprintf(F, " label: \"");
875 bad |= dump_node_opcode(F, con);
876 bad |= dump_node_mode(F, con);
877 bad |= dump_node_typeinfo(F, con);
879 bad |= dump_node_nodeattr(F, con);
880 fprintf(F, " %ld", get_irn_node_nr(con));
882 bad |= dump_node_info(F, con);
883 dump_node_vcgattr(F, con, bad);
889 static void INLINE print_node_error(FILE *F, const char *p)
894 fprintf (F, " info2: \"%s\"", p);
897 static void dump_node(FILE *F, ir_node *n)
902 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
904 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
906 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
907 bad |= dump_node_opcode(F, n);
908 bad |= dump_node_mode(F, n);
909 bad |= dump_node_typeinfo(F, n);
911 bad |= dump_node_nodeattr(F, n);
912 fprintf(F, " %ld", get_irn_node_nr(n));
914 bad |= dump_node_info(F, n);
915 print_node_error(F, p);
916 dump_node_vcgattr(F, n, bad);
918 dump_const_node_local(F, n);
925 /* dump the edge to the block this node belongs to */
927 dump_ir_block_edge(FILE *F, ir_node *n) {
928 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
929 if (is_no_Block(n)) {
930 ir_node *block = get_nodes_block(n);
932 fprintf (F, "edge: { sourcename: \"");
934 fprintf (F, "\" targetname: ");
935 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
936 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
941 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
942 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
943 fprintf (F, INTRA_DATA_EDGE_ATTR);
945 fprintf (F, INTER_DATA_EDGE_ATTR);
949 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
950 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
951 fprintf (F, INTRA_MEM_EDGE_ATTR);
953 fprintf (F, INTER_MEM_EDGE_ATTR);
957 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
960 if (dump_backedge_information_flag && is_backedge(from, to))
961 fprintf (F, BACK_EDGE_ATTR);
963 switch (get_irn_opcode(from)) {
965 fprintf (F, CF_EDGE_ATTR);
967 case iro_Start: break;
970 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
971 fprintf (F, CF_EDGE_ATTR);
972 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
973 fprintf (F, INTER_MEM_EDGE_ATTR);
981 print_data_edge_vcgattr(F, from, to);
986 print_mem_edge_vcgattr(F, from, to);
988 print_data_edge_vcgattr(F, from, to);
992 print_data_edge_vcgattr(F, from, to);
997 print_mem_edge_vcgattr(F, from, to);
999 print_data_edge_vcgattr(F, from, to);
1006 print_data_edge_vcgattr(F, from, to);
1013 print_mem_edge_vcgattr(F, from, to);
1015 print_data_edge_vcgattr(F, from, to);
1027 print_data_edge_vcgattr(F, from, to);
1030 if (get_irn_modecode(from) == irm_M)
1031 fprintf (F, INTER_MEM_EDGE_ATTR);
1033 print_data_edge_vcgattr(F, from, to);
1040 print_mem_edge_vcgattr(F, from, to);
1042 print_data_edge_vcgattr(F, from, to);
1045 print_mem_edge_vcgattr(F, from, to);
1047 case iro_Tuple: break;
1050 switch (get_irn_modecode(from)) {
1052 fprintf (F, CF_EDGE_ATTR);
1055 fprintf (F, INTER_MEM_EDGE_ATTR);
1058 print_data_edge_vcgattr(F, from, to);
1062 case iro_Bad: break;
1063 case iro_Unknown: break;
1065 switch (get_irn_modecode(from)) {
1067 fprintf (F, INTRA_MEM_EDGE_ATTR);
1070 fprintf (F, CF_EDGE_ATTR);
1073 print_data_edge_vcgattr(F, from, to);
1081 /* dump edges to our inputs */
1083 dump_ir_data_edges(FILE *F, ir_node *n) {
1084 int i, visited = get_irn_visited(n);
1086 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1089 for (i = 0; i < get_irn_arity(n); i++) {
1090 ir_node * pred = get_irn_n(n, i);
1093 if ((interprocedural_view && get_irn_visited(pred) < visited))
1094 continue; /* pred not dumped */
1096 if (dump_backedge_information_flag && is_backedge(n, i))
1097 fprintf (F, "backedge: {sourcename: \"");
1099 fprintf (F, "edge: {sourcename: \"");
1101 fprintf (F, "\" targetname: ");
1102 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1103 PRINT_CONSTID(n, pred);
1105 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1107 fprintf (F, " label: \"%d\" ", i);
1108 print_edge_vcgattr(F, n, i);
1113 /** Dumps a node and its edges but not the block edge
1116 dump_node_wo_blockedge (ir_node *n, void *env) {
1119 dump_ir_data_edges(F, n);
1122 /** Dumps a node and its edges.
1125 dump_whole_node (ir_node *n, void *env) {
1127 dump_node_wo_blockedge(n, env);
1128 if (!node_floats(n)) dump_ir_block_edge(F, n);
1132 dump_const_node(ir_node *n, void *env) {
1133 if (is_Block(n)) return;
1134 dump_node_wo_blockedge(n, env);
1137 /***********************************************************************/
1138 /* the following routines dump the nodes/irgs bracketed to graphs. */
1139 /***********************************************************************/
1141 /** Dumps a constant expression as entity initializer, array bound ...
1143 static void dump_const_expression(FILE *F, ir_node *value) {
1144 ir_graph *rem = current_ir_graph;
1145 int rem_dump_const_local = dump_const_local;
1146 dump_const_local = 0;
1147 current_ir_graph = get_const_code_irg();
1148 irg_walk(value, dump_const_node, NULL, F);
1149 /* Decrease visited flag so that we walk with the same flag for the next
1150 expresssion. This guarantees that we don't dump the same node twice,
1151 as for const expressions cse is performed to save memory. */
1152 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1153 current_ir_graph = rem;
1154 dump_const_local = rem_dump_const_local;
1157 /** Dump a block as graph containing its nodes.
1159 * Expects to find nodes belonging to the block as list in its
1161 * Dumps the edges of all nodes including itself. */
1163 dump_whole_block(FILE *F, ir_node *block) {
1165 assert(is_Block(block));
1167 fprintf(F, "graph: { title: \"");
1168 PRINT_NODEID(block);
1169 fprintf(F, "\" label: \"");
1170 dump_node_opcode(F, block);
1171 fprintf (F, " %ld", get_irn_node_nr(block));
1173 if (get_opt_dump_abstvals())
1174 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1176 fprintf(F, "\" status:clustered color:%s \n",
1177 get_Block_matured(block) ? "yellow" : "red");
1179 /* dump the blocks edges */
1180 dump_ir_data_edges(F, block);
1182 /* dump the nodes that go into the block */
1183 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1185 dump_ir_data_edges(F, node);
1188 /* Close the vcg information for the block */
1190 dump_const_node_local(F, block);
1192 dump_chi_term(F, block);
1197 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1198 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1200 dump_block_graph(FILE *F, ir_graph *irg) {
1202 ir_graph *rem = current_ir_graph;
1203 ir_node **arr = ird_get_irg_link(irg);
1204 current_ir_graph = irg;
1206 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1207 ir_node * node = arr[i];
1208 if (is_Block(node)) {
1209 /* Dumps the block and all the nodes in the block, which are to
1210 be found in Block->link. */
1211 dump_whole_block(F, node);
1213 /* Nodes that are not in a Block. */
1215 dump_ir_data_edges(F, node);
1219 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1220 dump_loop_nodes_into_graph(F, irg);
1222 current_ir_graph = rem;
1225 /** Dumps an irg as a graph.
1226 * If interprocedural view edges can point to nodes out of this graph.
1228 static void dump_graph(FILE *F, ir_graph *irg) {
1230 fprintf(F, "graph: { title: \"");
1232 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1233 get_ent_dump_name(get_irg_entity(irg)));
1235 dump_block_graph(F, irg);
1237 /* Close the vcg information for the irg */
1238 fprintf(F, "}\n\n");
1241 /*******************************************************************/
1242 /* Basic type and entity nodes and edges. */
1243 /*******************************************************************/
1245 /* dumps the edges between nodes and their type or entity attributes. */
1246 static void dump_node2type_edges(ir_node *n, void *env)
1251 switch (get_irn_opcode(n)) {
1253 /* @@@ some consts have an entity */
1256 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1257 || (get_SymConst_kind(n) ==symconst_size))
1259 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1263 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1266 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1269 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1272 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1275 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1283 static int print_type_info(FILE *F, type *tp) {
1286 if (get_type_state(tp) == layout_undefined) {
1287 fprintf(F, "state: layout_undefined\n");
1289 fprintf(F, "state: layout_fixed,\n");
1291 if (get_type_mode(tp))
1292 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1293 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1298 static void print_typespecific_info(FILE *F, type *tp) {
1299 switch (get_type_tpop_code(tp)) {
1302 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1309 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1310 fprintf(F, "params: %d\n", get_method_n_params(tp));
1311 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1319 case tpo_enumeration:
1333 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1334 switch (get_type_tpop_code(tp)) {
1337 if (peculiarity_existent == get_class_peculiarity(tp))
1338 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1340 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1344 fprintf (F, " " TYPE_METH_NODE_ATTR);
1355 case tpo_enumeration:
1368 static int print_type_node(FILE *F, type *tp)
1372 fprintf (F, "node: {title: ");
1374 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1375 fprintf (F, " info1: \"");
1376 bad |= print_type_info(F, tp);
1377 print_typespecific_info(F, tp);
1379 print_typespecific_vcgattr(F, tp);
1385 #define X(a) case a: fprintf(F, #a); break
1386 void dump_entity_node(FILE *F, entity *ent, int color)
1388 fprintf (F, "node: {title: \"");
1389 PRINT_ENTID(ent); fprintf(F, "\"");
1390 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1391 fprintf (F, "label: ");
1392 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1394 fprintf(F, "color: %d", color);
1396 fprintf (F, ENTITY_NODE_ATTR);
1397 fprintf (F, "\n info1: \"");
1399 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1401 fprintf(F, "\"\n}\n");
1405 static void dump_enum_item(FILE *F, type *tp, int pos)
1408 ident *id = get_enumeration_nameid(tp, pos);
1409 tarval *tv = get_enumeration_enum(tp, pos);
1411 tarval_snprintf(buf, sizeof(buf), tv);
1412 fprintf (F, "node: {title: \"");
1413 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1414 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1415 fprintf (F, "label: ");
1416 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1417 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1420 /* dumps a type or entity and it's edges. */
1422 dump_type_info(type_or_ent *tore, void *env) {
1424 int i = 0; /* to shutup gcc */
1426 /* dump this type or entity */
1428 switch (get_kind(tore)) {
1431 entity *ent = (entity *)tore;
1434 dump_entity_node(F, ent, 0);
1436 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1437 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1438 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1439 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1440 if(is_class_type(get_entity_owner(ent))) {
1441 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1442 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1444 /* attached subgraphs */
1445 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1446 if (is_atomic_entity(ent)) {
1447 value = get_atomic_ent_value(ent);
1449 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1450 /* DDMN(value); $$$ */
1451 dump_const_expression(F, value);
1454 if (is_compound_entity(ent)) {
1455 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1456 value = get_compound_ent_value(ent, i);
1458 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1459 dump_const_expression(F, value);
1460 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1462 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1463 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1464 get_compound_ent_value_member(ent, i), i);
1473 type *tp = (type *)tore;
1474 print_type_node(F, tp);
1475 /* and now the edges */
1476 switch (get_type_tpop_code(tp)) {
1479 for (i=0; i < get_class_n_supertypes(tp); i++)
1480 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1481 for (i=0; i < get_class_n_members(tp); i++)
1482 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1486 for (i=0; i < get_struct_n_members(tp); i++)
1487 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1491 for (i = 0; i < get_method_n_params(tp); i++)
1492 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1493 for (i = 0; i < get_method_n_ress(tp); i++)
1494 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1498 for (i = 0; i < get_union_n_members(tp); i++)
1499 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1503 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1504 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1505 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1506 ir_node *upper = get_array_upper_bound(tp, i);
1507 ir_node *lower = get_array_lower_bound(tp, i);
1508 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1509 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1510 dump_const_expression(F, upper);
1511 dump_const_expression(F, lower);
1515 case tpo_enumeration:
1517 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1518 dump_enum_item(F, tp, i);
1519 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1524 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1532 break; /* case k_type */
1535 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1537 } /* switch kind_or_entity */
1540 typedef struct _h_env {
1545 /** For dumping class hierarchies.
1546 * Dumps a class type node and a superclass edge.
1547 * If env->dump_ent dumps entities of classes and overwrites edges.
1550 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1553 int i = 0; /* to shutup gcc */
1555 /* dump this type or entity */
1556 switch (get_kind(tore)) {
1558 entity *ent = (entity *)tore;
1559 if (get_entity_owner(ent) == get_glob_type()) break;
1560 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1561 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1563 dump_entity_node(F, ent, 0);
1565 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1566 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1567 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1569 } break; /* case k_entity */
1572 type *tp = (type *)tore;
1573 if (tp == get_glob_type()) break;
1574 switch (get_type_tpop_code(tp)) {
1576 print_type_node(F, tp);
1577 /* and now the edges */
1578 for (i=0; i < get_class_n_supertypes(tp); i++)
1580 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1586 break; /* case k_type */
1589 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1591 } /* switch kind_or_entity */
1594 /*******************************************************************/
1595 /* dump analysis information that is expressed in graph terms. */
1596 /*******************************************************************/
1598 /* dump out edges */
1600 dump_out_edge(ir_node *n, void *env) {
1603 for (i = 0; i < get_irn_n_outs(n); i++) {
1604 assert(get_irn_out(n, i));
1605 fprintf (F, "edge: {sourcename: \"");
1607 fprintf (F, "\" targetname: \"");
1608 PRINT_NODEID(get_irn_out(n, i));
1609 fprintf (F, "\" color: red linestyle: dashed");
1615 dump_loop_label(FILE *F, ir_loop *loop) {
1616 fprintf (F, "loop %d, %d sons, %d nodes",
1617 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1620 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1621 fprintf (F, " info1: \"");
1622 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1623 #if DEBUG_libfirm /* GL @@@ debug analyses */
1624 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1630 dump_loop_node(FILE *F, ir_loop *loop) {
1631 fprintf (F, "node: {title: \"");
1633 fprintf (F, "\" label: \"");
1634 dump_loop_label(F, loop);
1636 dump_loop_info(F, loop);
1642 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1644 fprintf (F, "edge: {sourcename: \"");
1646 fprintf (F, "\" targetname: \"");
1647 PRINT_NODEID(get_loop_node(loop, i));
1648 fprintf (F, "\" color: green");
1653 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1655 fprintf (F, "edge: {sourcename: \"");
1657 fprintf (F, "\" targetname: \"");
1658 PRINT_LOOPID(get_loop_son(loop, i));
1659 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1660 get_loop_element_pos(loop, get_loop_son(loop, i)));
1664 void dump_loops(FILE *F, ir_loop *loop) {
1666 /* dump this loop node */
1667 dump_loop_node(F, loop);
1669 /* dump edges to nodes in loop -- only if it is a real loop */
1670 if (get_loop_depth(loop) != 0) {
1671 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1672 dump_loop_node_edge(F, loop, i);
1675 for (i = 0; i < get_loop_n_sons(loop); i++) {
1676 dump_loops(F, get_loop_son(loop, i));
1677 dump_loop_son_edge(F, loop, i);
1682 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1683 ir_graph *rem = current_ir_graph;
1684 current_ir_graph = irg;
1686 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1688 current_ir_graph = rem;
1693 * dumps the VCG header
1696 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1705 if (!orientation) orientation = "bottom_to_top";
1709 "graph: { title: \"ir graph of %s\"\n"
1710 "display_edge_labels: %s\n"
1711 "layoutalgorithm: mindepth\n"
1712 "manhattan_edges: yes\n"
1713 "port_sharing: no\n"
1715 "classname 1: \"intrablock Data\"\n"
1716 "classname 16: \"interblock Data\"\n"
1717 "classname 2: \"Block\"\n"
1718 "classname 13: \"Control Flow\"\n"
1719 "classname 14: \"intrablock Memory\"\n"
1720 "classname 17: \"interblock Memory\"\n"
1721 "classname 15: \"Dominators\"\n"
1722 "classname 3: \"Entity type\"\n"
1723 "classname 4: \"Entity owner\"\n"
1724 "classname 5: \"Method Param\"\n"
1725 "classname 6: \"Method Res\"\n"
1726 "classname 7: \"Super\"\n"
1727 "classname 8: \"Union\"\n"
1728 "classname 9: \"Points-to\"\n"
1729 "classname 10: \"Array Element Type\"\n"
1730 "classname 11: \"Overwrites\"\n"
1731 "classname 12: \"Member\"\n"
1732 "infoname 1: \"Attribute\"\n"
1733 "infoname 2: \"Verification errors\"\n",
1734 name, label, orientation);
1736 /* don't use all, the range is too whith/black. */
1740 "colorentry 100: 0 0 0\n"
1741 "colorentry 101: 20 0 0\n"
1742 "colorentry 102: 40 0 0\n"
1743 "colorentry 103: 60 0 0\n"
1744 "colorentry 104: 80 0 0\n"
1745 "colorentry 105: 100 0 0\n"
1746 "colorentry 106: 120 0 0\n"
1747 "colorentry 107: 140 0 0\n"
1748 "colorentry 108: 150 0 0\n"
1749 "colorentry 109: 180 0 0\n"
1750 "colorentry 110: 200 0 0\n"
1751 "colorentry 111: 220 0 0\n"
1752 "colorentry 112: 240 0 0\n"
1753 "colorentry 113: 255 0 0\n"
1754 "colorentry 113: 255 20 20\n"
1755 "colorentry 114: 255 40 40\n"
1756 "colorentry 115: 255 60 60\n"
1757 "colorentry 116: 255 80 80\n"
1758 "colorentry 117: 255 100 100\n"
1759 "colorentry 118: 255 120 120\n"
1760 "colorentry 119: 255 140 140\n"
1761 "colorentry 120: 255 150 150\n"
1762 "colorentry 121: 255 180 180\n"
1763 "colorentry 122: 255 200 200\n"
1764 "colorentry 123: 255 220 220\n"
1765 "colorentry 124: 255 240 240\n"
1766 "colorentry 125: 255 250 250\n"
1769 fprintf (F, "\n"); /* a separator */
1775 * @param irg The graph to be dumped
1776 * @param suffix1 first filename suffix
1777 * @param suffix2 second filename suffix
1779 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1781 const char *nm = get_irg_dump_name(irg);
1782 int len = strlen(nm), i, j;
1783 char *fname; /* filename to put the vcg information in */
1785 if (!suffix1) suffix1 = "";
1786 if (!suffix2) suffix2 = "";
1788 /* open file for vcg graph */
1789 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1791 /* strncpy (fname, nm, len); */ /* copy the filename */
1793 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1795 fname[j] = '@'; j++; fname[j] = '1'; j++;
1796 } else if (nm[i] == '@') {
1797 fname[j] = '@'; j++; fname[j] = '2'; j++;
1799 fname[j] = nm[i]; j++;
1803 strcat (fname, suffix1); /* append file suffix */
1804 strcat (fname, suffix2); /* append file suffix */
1805 strcat (fname, ".vcg"); /* append the .vcg suffix */
1806 F = fopen (fname, "w"); /* open file for writing */
1808 panic("cannot open %s for writing (%m)", fname); /* not reached */
1818 * @param irg The graph to be dumped
1819 * @param suffix filename suffix
1821 static FILE *vcg_open_name (const char *name, const char *suffix) {
1823 char *fname; /* filename to put the vcg information in */
1824 int i, j, len = strlen(name);
1826 if (!suffix) suffix = "";
1828 /** open file for vcg graph */
1829 fname = malloc (len * 2 + 5 + strlen(suffix));
1830 /* strcpy (fname, name);*/ /* copy the filename */
1832 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1833 if (name[i] == '/') {
1834 fname[j] = '@'; j++; fname[j] = '1'; j++;
1835 } else if (name[i] == '@') {
1836 fname[j] = '@'; j++; fname[j] = '2'; j++;
1838 fname[j] = name[i]; j++;
1842 strcat (fname, suffix);
1843 strcat (fname, ".vcg"); /* append the .vcg suffix */
1844 F = fopen (fname, "w"); /* open file for writing */
1846 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1854 * Dumps the vcg file footer
1856 static INLINE void dump_vcg_footer (FILE *F) {
1861 * close the vcg file
1864 vcg_close (FILE *F) {
1865 dump_vcg_footer(F); /* print footer */
1866 fclose (F); /* close vcg file */
1869 /************************************************************************/
1870 /************************************************************************/
1871 /* Routines that dump all or parts of the firm representation to a file */
1872 /************************************************************************/
1873 /************************************************************************/
1875 /************************************************************************/
1876 /* Dump ir graphs, differnt formats and additional information. */
1877 /************************************************************************/
1879 /** Routine to dump a graph, blocks as conventional nodes.
1882 dump_ir_graph (ir_graph *irg, const char *suffix )
1887 rem = current_ir_graph;
1889 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1890 current_ir_graph = irg;
1891 if (interprocedural_view) suffix1 = "-pure-ip";
1892 else suffix1 = "-pure";
1893 f = vcg_open(irg, suffix, suffix1);
1894 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1896 /* walk over the graph */
1897 /* dump_whole_node must be called in post visiting predecessors */
1898 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1900 /* dump the out edges in a separate walk */
1901 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1902 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1907 current_ir_graph = rem;
1912 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1918 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1921 if (interprocedural_view) suffix1 = "-ip";
1923 f = vcg_open(irg, suffix, suffix1);
1924 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1926 construct_block_lists(irg);
1928 for (i = 0; i < get_irp_n_irgs(); i++) {
1929 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1931 dump_graph(f, get_irp_irg(i));
1939 /** dumps a graph with type information
1942 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1945 ir_graph *rem = current_ir_graph;
1948 /* if a filter is set, dump only the irg's that match the filter */
1949 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1952 current_ir_graph = irg;
1954 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1955 else suffix1 = "-pure-wtypes";
1956 f = vcg_open(irg,suffix, suffix1);
1957 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1959 /* dump common ir graph */
1960 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1961 /* dump type info */
1962 type_walk_irg(irg, dump_type_info, NULL, f);
1963 inc_irg_visited(get_const_code_irg());
1964 /* dump edges from graph to type info */
1965 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1968 current_ir_graph = rem;
1972 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1977 ir_graph *rem = current_ir_graph;
1979 /* if a filter is set, dump only the irg's that match the filter */
1980 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1983 if (interprocedural_view) suffix1 = "-wtypes-ip";
1984 else suffix1 = "-wtypes";
1985 f = vcg_open(irg, suffix, suffix1);
1986 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1988 /* dump common blocked ir graph */
1989 construct_block_lists(irg);
1991 for (i = 0; i < get_irp_n_irgs(); i++) {
1992 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1994 dump_graph(f, get_irp_irg(i));
1999 /* dump type info */
2000 current_ir_graph = irg;
2001 type_walk_irg(irg, dump_type_info, NULL, f);
2002 inc_irg_visited(get_const_code_irg());
2004 /* dump edges from graph to type info */
2005 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2007 current_ir_graph = rem;
2011 /*---------------------------------------------------------------------*/
2012 /* The following routines dump a control flow graph. */
2013 /*---------------------------------------------------------------------*/
2016 dump_block_to_cfg(ir_node *block, void *env) {
2021 if (is_Block(block)) {
2022 /* This is a block. Dump a node for the block. */
2023 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2024 fprintf (F, "\" label: \"");
2025 if (block == get_irg_start_block(get_irn_irg(block)))
2026 fprintf(F, "Start ");
2027 if (block == get_irg_end_block(get_irn_irg(block)))
2030 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2031 PRINT_NODEID(block);
2033 fprintf(F, "info1:\"");
2034 if (dump_dominator_information_flag)
2035 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2037 /* show arity and possible Bad predecessors of the block */
2038 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2039 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2040 ir_node *pred = get_Block_cfgpred(block, i);
2043 fprintf(F, "Bad pred at pos: ");
2044 fprintf(F, "%d ", i);
2051 fprintf (F, "\""); /* closing quote of info */
2053 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2054 (block == get_irg_end_block(get_irn_irg(block))) )
2055 fprintf(F, " color:blue ");
2057 fprintf(F, " color:yellow ");
2060 /* Dump the edges */
2061 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2062 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2063 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2064 fprintf (F, "edge: { sourcename: \"");
2065 PRINT_NODEID(block);
2066 fprintf (F, "\" targetname: \"");
2068 fprintf (F, "\"}\n");
2071 /* Dump dominator edge */
2072 if (dump_dominator_information_flag && get_Block_idom(block)) {
2073 pred = get_Block_idom(block);
2074 fprintf (F, "edge: { sourcename: \"");
2075 PRINT_NODEID(block);
2076 fprintf (F, "\" targetname: \"");
2078 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2084 dump_cfg (ir_graph *irg, const char *suffix)
2087 ir_graph *rem = current_ir_graph;
2088 int ddif = dump_dominator_information_flag;
2089 int ipv = interprocedural_view;
2091 /* if a filter is set, dump only the irg's that match the filter */
2092 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2095 current_ir_graph = irg;
2097 f = vcg_open(irg, suffix, "-cfg");
2098 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2100 if (interprocedural_view) {
2101 printf("Warning: dumping cfg not in interprocedural view!\n");
2102 interprocedural_view = 0;
2105 if (get_irg_dom_state(irg) != dom_consistent)
2106 dump_dominator_information_flag = 0;
2108 /* walk over the blocks in the graph */
2109 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2110 dump_node(f, get_irg_bad(irg));
2112 dump_dominator_information_flag = ddif;
2113 interprocedural_view = ipv;
2115 current_ir_graph = rem;
2118 static int weight_overall(int rec, int loop) {
2119 return 2*rec + loop;
2122 static int compute_color (int my, int max) {
2127 /* if small, scale to the full color range. */
2129 my = my * (n_colors/max);
2131 int step = 1 + (max / n_colors);
2135 return base_color + n_colors - color;
2138 static int get_entity_color(entity *ent) {
2139 assert(get_entity_irg(ent));
2140 ir_graph *irg = get_entity_irg(ent);
2142 int rec_depth = get_irg_recursion_depth(irg);
2143 int loop_depth = get_irg_loop_depth(irg);
2144 int overall_depth = weight_overall(rec_depth, loop_depth);
2146 int max_rec_depth = irp->max_callgraph_recursion_depth;
2147 int max_loop_depth = irp->max_callgraph_loop_depth;
2148 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2150 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2151 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2152 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2154 return my_overall_color;
2157 void dump_callgraph(const char *suffix) {
2159 int i, n_irgs = get_irp_n_irgs();
2160 int rem = edge_label;
2162 //ident *prefix = new_id_from_str("java/");
2164 F = vcg_open_name("Callgraph", suffix);
2165 dump_vcg_header(F, "Callgraph", NULL);
2167 for (i = 0; i < n_irgs; ++i) {
2168 ir_graph *irg = get_irp_irg(i);
2169 entity *ent = get_irg_entity(irg);
2170 int j, n_callees = get_irg_n_callees(irg);
2172 /* Do not dump runtime system. */
2173 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2175 dump_entity_node(F, ent, get_entity_color(ent));
2176 for (j = 0; j < n_callees; ++j) {
2177 entity *c = get_irg_entity(get_irg_callee(irg, j));
2178 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2179 int be = is_irg_callee_backedge(irg, j);
2182 "label:\"recursion %d\" color: %d" :
2183 "label:\"calls %d\" color: %d";
2184 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2192 /* Dump all irgs in interprocedural view to a single file. */
2193 void dump_all_cg_block_graph(const char *suffix) {
2196 int rem_view = interprocedural_view;
2197 interprocedural_view = 1;
2199 f = vcg_open_name("All_graphs", suffix);
2200 dump_vcg_header(f, "All_graphs", NULL);
2202 /* collect nodes in all irgs reachable in call graph*/
2203 for (i = 0; i < get_irp_n_irgs(); i++)
2204 ird_set_irg_link(get_irp_irg(i), NULL);
2206 cg_walk(clear_link, collect_node, NULL);
2208 /* dump all graphs */
2209 for (i = 0; i < get_irp_n_irgs(); i++) {
2210 current_ir_graph = get_irp_irg(i);
2211 assert(ird_get_irg_link(current_ir_graph));
2212 dump_graph(f, current_ir_graph);
2213 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2217 interprocedural_view = rem_view;
2220 /***********************************************************************/
2221 /* the following routines dumps type information without any ir nodes. */
2222 /***********************************************************************/
2225 dump_type_graph (ir_graph *irg, const char *suffix)
2229 rem = current_ir_graph;
2231 /* if a filter is set, dump only the irg's that match the filter */
2232 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2234 current_ir_graph = irg;
2236 f = vcg_open(irg, suffix, "-type");
2237 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2239 /* walk over the blocks in the graph */
2240 type_walk_irg(irg, dump_type_info, NULL, f);
2241 /* The walker for the const code can be called several times for the
2242 same (sub) experssion. So that no nodes are dumped several times
2243 we decrease the visited flag of the corresponding graph after each
2244 walk. So now increase it finally. */
2245 inc_irg_visited(get_const_code_irg());
2248 current_ir_graph = rem;
2252 dump_all_types (const char *suffix)
2254 FILE *f = vcg_open_name("All_types", suffix);
2255 dump_vcg_header(f, "All_types", NULL);
2256 type_walk(dump_type_info, NULL, f);
2257 inc_irg_visited(get_const_code_irg());
2262 dump_class_hierarchy (bool entities, const char *suffix)
2264 FILE *f = vcg_open_name("class_hierarchy", suffix);
2268 dump_vcg_header(f, "class_hierarchy", NULL);
2273 type_walk(dump_class_hierarchy_node, NULL, &env);
2277 /***********************************************************************/
2278 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2280 /* dump_ir_block_graph */
2282 /* dump_type_graph */
2283 /* dump_ir_graph_w_types */
2284 /***********************************************************************/
2286 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2287 int i, n_irgs = get_irp_n_irgs();
2288 for (i = 0; i < n_irgs; ++i) {
2289 dmp_grph(get_irp_irg(i), suffix);
2294 /**********************************************************************************
2295 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2296 * packed together in one subgraph/box *
2297 **********************************************************************************/
2299 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2300 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2302 ir_loop *son = NULL;
2304 /* Dump a new loop node. */
2305 dump_loop_node(F, loop);
2307 /* Dump the loop elements. */
2309 for(i = 0; i < get_loop_n_elements(loop); i++) {
2310 le = get_loop_element(loop, i);
2312 if (get_kind(son) == k_ir_loop) {
2314 /* We are a loop son -> Recurse */
2316 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2317 fprintf(F, "\" }\n");
2318 fprintf (F, "edge: {sourcename: \"");
2320 fprintf (F, "\" targetname: \"");
2322 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2323 loop_node_started = 0;
2325 dump_loop_son_edge(F, loop, son_number++);
2326 dump_loops_standalone(F, son);
2327 } else if (get_kind(son) == k_ir_node) {
2328 /* We are a loop node -> Collect firm nodes */
2330 ir_node *n = le.node;
2333 if (!loop_node_started) {
2334 /* Start a new node which contains all firm nodes of the current loop */
2335 fprintf (F, "node: { title: \"");
2337 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2338 loop_node_started = 1;
2344 bad |= dump_node_opcode(F, n);
2345 bad |= dump_node_mode(F, n);
2346 bad |= dump_node_typeinfo(F, n);
2348 bad |= dump_node_nodeattr(F, n);
2349 fprintf (F, " %ld", get_irn_node_nr(n));
2350 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2351 } else { /* for callgraph loop tree */
2352 assert(get_kind(son) == k_ir_graph);
2353 /* We are a loop node -> Collect firm graphs */
2354 ir_graph *n = (ir_graph *)le.node;
2355 if (!loop_node_started) {
2356 /* Start a new node which contains all firm nodes of the current loop */
2357 fprintf (F, "node: { title: \"");
2359 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2360 loop_node_started = 1;
2365 fprintf (F, " %s", get_irg_dump_name(n));
2366 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2370 if (loop_node_started) {
2371 fprintf(F, "\" }\n");
2372 fprintf (F, "edge: {sourcename: \"");
2374 fprintf (F, "\" targetname: \"");
2376 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2377 loop_node_started = 0;
2381 void dump_loop_tree(ir_graph *irg, const char *suffix)
2384 ir_graph *rem = current_ir_graph;
2385 int el_rem = edge_label;
2388 /* if a filter is set, dump only the irg's that match the filter */
2389 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2392 current_ir_graph = irg;
2394 f = vcg_open(irg, suffix, "-looptree");
2395 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2397 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2401 edge_label = el_rem;
2402 current_ir_graph = rem;
2405 void dump_callgraph_loop_tree(const char *suffix) {
2407 F = vcg_open_name("Callgraph_looptree", suffix);
2408 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2409 dump_loops_standalone(F, irp->outermost_cg_loop);
2414 /*******************************************************************************/
2415 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2416 /*******************************************************************************/
2418 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2419 int i, son_number = 0, node_number = 0;
2421 if (dump_loop_information_flag) dump_loop_node(F, loop);
2423 for (i = 0; i < get_loop_n_elements(loop); i++) {
2424 loop_element le = get_loop_element(loop, i);
2425 if (*(le.kind) == k_ir_loop) {
2426 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2428 collect_nodeloop(F, le.son, loopnodes);
2430 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2431 eset_insert(loopnodes, le.node);
2436 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2439 for(i = 0; i < get_loop_n_elements(loop); i++) {
2440 loop_element le = get_loop_element(loop, i);
2441 if (*(le.kind) == k_ir_loop) {
2443 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2445 if (is_Block(le.node)) start = 0; else start = -1;
2446 for (j = start; j < get_irn_arity(le.node); j++) {
2447 ir_node *pred = get_irn_n(le.node, j);
2448 if (!eset_contains(loopnodes, pred)) {
2449 eset_insert(extnodes, pred);
2450 if (!is_Block(pred)) {
2451 pred = get_nodes_block(pred);
2452 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2460 void dump_loop(ir_loop *l, const char *suffix) {
2463 eset *loopnodes = eset_create();
2464 eset *extnodes = eset_create();
2467 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2468 F = vcg_open_name (name, suffix);
2469 dump_vcg_header(F, name, NULL);
2471 /* collect all nodes to dump */
2472 collect_nodeloop(F, l, loopnodes);
2473 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2475 /* build block lists */
2476 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2477 set_irn_link(n, NULL);
2478 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2479 set_irn_link(n, NULL);
2480 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2482 b = get_nodes_block(n);
2483 set_irn_link(n, get_irn_link(b));
2486 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2488 b = get_nodes_block(n);
2489 set_irn_link(n, get_irn_link(b));
2493 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2495 fprintf(F, "graph: { title: \"");
2497 fprintf(F, "\" label: \"");
2498 dump_node_opcode(F, b);
2499 fprintf (F, " %ld", get_irn_node_nr(b));
2500 fprintf(F, "\" status:clustered color:yellow\n");
2502 /* dump the blocks edges */
2503 dump_ir_data_edges(F, b);
2505 /* dump the nodes that go into the block */
2506 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2507 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2509 overrule_nodecolor = NULL;
2510 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2513 /* Close the vcg information for the block */
2515 dump_const_node_local(F, b);
2518 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2520 fprintf(F, "graph: { title: \"");
2522 fprintf(F, "\" label: \"");
2523 dump_node_opcode(F, b);
2524 fprintf (F, " %ld", get_irn_node_nr(b));
2525 fprintf(F, "\" status:clustered color:lightblue\n");
2527 /* dump the nodes that go into the block */
2528 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2529 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2531 overrule_nodecolor = NULL;
2532 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2535 /* Close the vcg information for the block */
2537 dump_const_node_local(F, b);
2541 eset_destroy(loopnodes);
2542 eset_destroy(extnodes);