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 for (i = 0; i < get_method_n_params(tp); ++i)
746 fprintf(F, " param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
747 for (i = 0; i < get_method_n_ress(tp); ++i)
748 fprintf(F, " resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
749 if (Call_has_callees(n)) {
750 fprintf(F, "possible callees: \n");
751 for (i = 0; i < get_Call_n_callees(n); i++) {
752 if (!get_Call_callee(n, i)) {
753 fprintf(F, " %d external method\n", i);
755 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
760 case iro_CallBegin: {
761 ir_node *call = get_CallBegin_call(n);
762 if (Call_has_callees(call)) {
763 fprintf(F, "possible callees: \n");
764 for (i = 0; i < get_Call_n_callees(call); i++) {
765 if (!get_Call_callee(call, i)) {
766 fprintf(F, " %d external method\n", i);
768 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
774 if (!interprocedural_view) {
775 type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
776 fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
777 for (i = 0; i < get_method_n_ress(tp); ++i)
778 fprintf(F, " res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
782 type *tp = get_Const_type(n);
783 assert(tp != none_type);
784 fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
787 switch(get_SymConst_kind(n)) {
788 case symconst_addr_name:
789 fprintf(F, "kind addr_name\n");
791 case symconst_addr_ent:
792 fprintf(F, "kind addr_ent\n");
793 dump_entity_to_file(F, get_SymConst_entity(n), dump_verbosity_onlynames);
795 case symconst_type_tag:
796 fprintf(F, "kind type_tag\n");
799 fprintf(F, "kind size\n");
805 if (interprocedural_view) {
806 fprintf(F, "intra predecessor nodes:\n");
807 for (i = 0; i < get_irn_intra_arity(n); i++) {
808 ir_node *pred = get_irn_intra_n(n, i);
809 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
812 fprintf(F, "inter predecessor nodes:\n");
813 for (i = 0; i < get_irn_inter_arity(n); i++) {
814 ir_node *pred = get_irn_inter_n(n, i);
815 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
816 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
821 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
824 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
830 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
831 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
832 if (get_irn_type(n) != none_type)
833 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
842 bool is_constlike_node(ir_node *n) {
843 ir_op *op = get_irn_op(n);
844 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
848 /* outputs the predecessors of n, that are constants, local. I.e.,
849 generates a copy of the constant predecessors for each node called with. */
850 static void dump_const_node_local(FILE *F, ir_node *n) {
852 if (!get_opt_dump_const_local()) return;
854 /* Use visited flag to avoid outputting nodes twice.
855 initialize it first. */
856 for (i = 0; i < get_irn_arity(n); i++) {
857 ir_node *con = get_irn_n(n, i);
858 if (is_constlike_node(con)) {
859 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
863 for (i = 0; i < get_irn_arity(n); i++) {
864 ir_node *con = get_irn_n(n, i);
865 if (is_constlike_node(con) && irn_not_visited(con)) {
868 mark_irn_visited(con);
869 /* Generate a new name for the node by appending the names of
871 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
872 fprintf(F, " label: \"");
873 bad |= dump_node_opcode(F, con);
874 bad |= dump_node_mode(F, con);
875 bad |= dump_node_typeinfo(F, con);
877 bad |= dump_node_nodeattr(F, con);
878 fprintf(F, " %ld", get_irn_node_nr(con));
880 bad |= dump_node_info(F, con);
881 dump_node_vcgattr(F, con, bad);
887 static void INLINE print_node_error(FILE *F, const char *p)
892 fprintf (F, " info2: \"%s\"", p);
895 static void dump_node(FILE *F, ir_node *n)
900 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
902 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
904 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
905 bad |= dump_node_opcode(F, n);
906 bad |= dump_node_mode(F, n);
907 bad |= dump_node_typeinfo(F, n);
909 bad |= dump_node_nodeattr(F, n);
910 fprintf(F, " %ld", get_irn_node_nr(n));
912 bad |= dump_node_info(F, n);
913 print_node_error(F, p);
914 dump_node_vcgattr(F, n, bad);
916 dump_const_node_local(F, n);
923 /* dump the edge to the block this node belongs to */
925 dump_ir_block_edge(FILE *F, ir_node *n) {
926 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
927 if (is_no_Block(n)) {
928 ir_node *block = get_nodes_block(n);
930 fprintf (F, "edge: { sourcename: \"");
932 fprintf (F, "\" targetname: ");
933 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
934 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
939 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
940 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
941 fprintf (F, INTRA_DATA_EDGE_ATTR);
943 fprintf (F, INTER_DATA_EDGE_ATTR);
947 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
948 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
949 fprintf (F, INTRA_MEM_EDGE_ATTR);
951 fprintf (F, INTER_MEM_EDGE_ATTR);
955 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
958 if (dump_backedge_information_flag && is_backedge(from, to))
959 fprintf (F, BACK_EDGE_ATTR);
961 switch (get_irn_opcode(from)) {
963 fprintf (F, CF_EDGE_ATTR);
965 case iro_Start: break;
968 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
969 fprintf (F, CF_EDGE_ATTR);
970 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
971 fprintf (F, INTER_MEM_EDGE_ATTR);
979 print_data_edge_vcgattr(F, from, to);
984 print_mem_edge_vcgattr(F, from, to);
986 print_data_edge_vcgattr(F, from, to);
990 print_data_edge_vcgattr(F, from, to);
995 print_mem_edge_vcgattr(F, from, to);
997 print_data_edge_vcgattr(F, from, to);
1004 print_data_edge_vcgattr(F, from, to);
1011 print_mem_edge_vcgattr(F, from, to);
1013 print_data_edge_vcgattr(F, from, to);
1025 print_data_edge_vcgattr(F, from, to);
1028 if (get_irn_modecode(from) == irm_M)
1029 fprintf (F, INTER_MEM_EDGE_ATTR);
1031 print_data_edge_vcgattr(F, from, to);
1038 print_mem_edge_vcgattr(F, from, to);
1040 print_data_edge_vcgattr(F, from, to);
1043 print_mem_edge_vcgattr(F, from, to);
1045 case iro_Tuple: break;
1048 switch (get_irn_modecode(from)) {
1050 fprintf (F, CF_EDGE_ATTR);
1053 fprintf (F, INTER_MEM_EDGE_ATTR);
1056 print_data_edge_vcgattr(F, from, to);
1060 case iro_Bad: break;
1061 case iro_Unknown: break;
1063 switch (get_irn_modecode(from)) {
1065 fprintf (F, INTRA_MEM_EDGE_ATTR);
1068 fprintf (F, CF_EDGE_ATTR);
1071 print_data_edge_vcgattr(F, from, to);
1079 /* dump edges to our inputs */
1081 dump_ir_data_edges(FILE *F, ir_node *n) {
1082 int i, visited = get_irn_visited(n);
1084 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1087 for (i = 0; i < get_irn_arity(n); i++) {
1088 ir_node * pred = get_irn_n(n, i);
1091 if ((interprocedural_view && get_irn_visited(pred) < visited))
1092 continue; /* pred not dumped */
1094 if (dump_backedge_information_flag && is_backedge(n, i))
1095 fprintf (F, "backedge: {sourcename: \"");
1097 fprintf (F, "edge: {sourcename: \"");
1099 fprintf (F, "\" targetname: ");
1100 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1101 PRINT_CONSTID(n, pred);
1103 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1105 fprintf (F, " label: \"%d\" ", i);
1106 print_edge_vcgattr(F, n, i);
1111 /** Dumps a node and its edges but not the block edge
1114 dump_node_wo_blockedge (ir_node *n, void *env) {
1117 dump_ir_data_edges(F, n);
1120 /** Dumps a node and its edges.
1123 dump_whole_node (ir_node *n, void *env) {
1125 dump_node_wo_blockedge(n, env);
1126 if (!node_floats(n)) dump_ir_block_edge(F, n);
1130 dump_const_node(ir_node *n, void *env) {
1131 if (is_Block(n)) return;
1132 dump_node_wo_blockedge(n, env);
1135 /***********************************************************************/
1136 /* the following routines dump the nodes/irgs bracketed to graphs. */
1137 /***********************************************************************/
1139 /** Dumps a constant expression as entity initializer, array bound ...
1141 static void dump_const_expression(FILE *F, ir_node *value) {
1142 ir_graph *rem = current_ir_graph;
1143 int rem_dump_const_local = dump_const_local;
1144 dump_const_local = 0;
1145 current_ir_graph = get_const_code_irg();
1146 irg_walk(value, dump_const_node, NULL, F);
1147 /* Decrease visited flag so that we walk with the same flag for the next
1148 expresssion. This guarantees that we don't dump the same node twice,
1149 as for const expressions cse is performed to save memory. */
1150 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1151 current_ir_graph = rem;
1152 dump_const_local = rem_dump_const_local;
1155 /** Dump a block as graph containing its nodes.
1157 * Expects to find nodes belonging to the block as list in its
1159 * Dumps the edges of all nodes including itself. */
1161 dump_whole_block(FILE *F, ir_node *block) {
1163 assert(is_Block(block));
1165 fprintf(F, "graph: { title: \"");
1166 PRINT_NODEID(block);
1167 fprintf(F, "\" label: \"");
1168 dump_node_opcode(F, block);
1169 fprintf (F, " %ld", get_irn_node_nr(block));
1171 if (get_opt_dump_abstvals())
1172 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1174 fprintf(F, "\" status:clustered color:%s \n",
1175 get_Block_matured(block) ? "yellow" : "red");
1177 /* dump the blocks edges */
1178 dump_ir_data_edges(F, block);
1180 /* dump the nodes that go into the block */
1181 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1183 dump_ir_data_edges(F, node);
1186 /* Close the vcg information for the block */
1188 dump_const_node_local(F, block);
1190 dump_chi_term(F, block);
1195 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1196 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1198 dump_block_graph(FILE *F, ir_graph *irg) {
1200 ir_graph *rem = current_ir_graph;
1201 ir_node **arr = ird_get_irg_link(irg);
1202 current_ir_graph = irg;
1204 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1205 ir_node * node = arr[i];
1206 if (is_Block(node)) {
1207 /* Dumps the block and all the nodes in the block, which are to
1208 be found in Block->link. */
1209 dump_whole_block(F, node);
1211 /* Nodes that are not in a Block. */
1213 dump_ir_data_edges(F, node);
1217 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1218 dump_loop_nodes_into_graph(F, irg);
1220 current_ir_graph = rem;
1223 /** Dumps an irg as a graph.
1224 * If interprocedural view edges can point to nodes out of this graph.
1226 static void dump_graph(FILE *F, ir_graph *irg) {
1228 fprintf(F, "graph: { title: \"");
1230 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1231 get_ent_dump_name(get_irg_entity(irg)));
1233 dump_block_graph(F, irg);
1235 /* Close the vcg information for the irg */
1236 fprintf(F, "}\n\n");
1239 /*******************************************************************/
1240 /* Basic type and entity nodes and edges. */
1241 /*******************************************************************/
1243 /* dumps the edges between nodes and their type or entity attributes. */
1244 static void dump_node2type_edges(ir_node *n, void *env)
1249 switch (get_irn_opcode(n)) {
1251 /* @@@ some consts have an entity */
1254 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1255 || (get_SymConst_kind(n) ==symconst_size))
1257 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1261 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1264 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1267 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1270 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1273 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1281 static int print_type_info(FILE *F, type *tp) {
1284 if (get_type_state(tp) == layout_undefined) {
1285 fprintf(F, "state: layout_undefined\n");
1287 fprintf(F, "state: layout_fixed,\n");
1289 if (get_type_mode(tp))
1290 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1291 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1296 static void print_typespecific_info(FILE *F, type *tp) {
1297 switch (get_type_tpop_code(tp)) {
1300 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1307 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1308 fprintf(F, "params: %d\n", get_method_n_params(tp));
1309 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1317 case tpo_enumeration:
1331 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1332 switch (get_type_tpop_code(tp)) {
1335 if (peculiarity_existent == get_class_peculiarity(tp))
1336 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1338 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1342 fprintf (F, " " TYPE_METH_NODE_ATTR);
1353 case tpo_enumeration:
1366 static int print_type_node(FILE *F, type *tp)
1370 fprintf (F, "node: {title: ");
1372 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1373 fprintf (F, " info1: \"");
1374 bad |= print_type_info(F, tp);
1375 print_typespecific_info(F, tp);
1377 print_typespecific_vcgattr(F, tp);
1383 #define X(a) case a: fprintf(F, #a); break
1384 void dump_entity_node(FILE *F, entity *ent, int color)
1386 fprintf (F, "node: {title: \"");
1387 PRINT_ENTID(ent); fprintf(F, "\"");
1388 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1389 fprintf (F, "label: ");
1390 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1392 fprintf(F, "color: %d", color);
1394 fprintf (F, ENTITY_NODE_ATTR);
1395 fprintf (F, "\n info1: \"");
1397 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1399 fprintf(F, "\"\n}\n");
1403 static void dump_enum_item(FILE *F, type *tp, int pos)
1406 ident *id = get_enumeration_nameid(tp, pos);
1407 tarval *tv = get_enumeration_enum(tp, pos);
1409 tarval_snprintf(buf, sizeof(buf), tv);
1410 fprintf (F, "node: {title: \"");
1411 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1412 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1413 fprintf (F, "label: ");
1414 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1415 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1418 /* dumps a type or entity and it's edges. */
1420 dump_type_info(type_or_ent *tore, void *env) {
1422 int i = 0; /* to shutup gcc */
1424 /* dump this type or entity */
1426 switch (get_kind(tore)) {
1429 entity *ent = (entity *)tore;
1432 dump_entity_node(F, ent, 0);
1434 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1435 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1436 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1437 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1438 if(is_class_type(get_entity_owner(ent))) {
1439 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1440 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1442 /* attached subgraphs */
1443 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1444 if (is_atomic_entity(ent)) {
1445 value = get_atomic_ent_value(ent);
1447 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1448 /* DDMN(value); $$$ */
1449 dump_const_expression(F, value);
1452 if (is_compound_entity(ent)) {
1453 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1454 value = get_compound_ent_value(ent, i);
1456 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1457 dump_const_expression(F, value);
1458 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1460 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1461 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1462 get_compound_ent_value_member(ent, i), i);
1471 type *tp = (type *)tore;
1472 print_type_node(F, tp);
1473 /* and now the edges */
1474 switch (get_type_tpop_code(tp)) {
1477 for (i=0; i < get_class_n_supertypes(tp); i++)
1478 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1479 for (i=0; i < get_class_n_members(tp); i++)
1480 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1484 for (i=0; i < get_struct_n_members(tp); i++)
1485 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1489 for (i = 0; i < get_method_n_params(tp); i++)
1490 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1491 for (i = 0; i < get_method_n_ress(tp); i++)
1492 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1496 for (i = 0; i < get_union_n_members(tp); i++)
1497 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1501 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1502 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1503 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1504 ir_node *upper = get_array_upper_bound(tp, i);
1505 ir_node *lower = get_array_lower_bound(tp, i);
1506 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1507 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1508 dump_const_expression(F, upper);
1509 dump_const_expression(F, lower);
1513 case tpo_enumeration:
1515 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1516 dump_enum_item(F, tp, i);
1517 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1522 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1530 break; /* case k_type */
1533 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1535 } /* switch kind_or_entity */
1538 typedef struct _h_env {
1543 /** For dumping class hierarchies.
1544 * Dumps a class type node and a superclass edge.
1545 * If env->dump_ent dumps entities of classes and overwrites edges.
1548 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1551 int i = 0; /* to shutup gcc */
1553 /* dump this type or entity */
1554 switch (get_kind(tore)) {
1556 entity *ent = (entity *)tore;
1557 if (get_entity_owner(ent) == get_glob_type()) break;
1558 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1559 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1561 dump_entity_node(F, ent, 0);
1563 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1564 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1565 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1567 } break; /* case k_entity */
1570 type *tp = (type *)tore;
1571 if (tp == get_glob_type()) break;
1572 switch (get_type_tpop_code(tp)) {
1574 print_type_node(F, tp);
1575 /* and now the edges */
1576 for (i=0; i < get_class_n_supertypes(tp); i++)
1578 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1584 break; /* case k_type */
1587 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1589 } /* switch kind_or_entity */
1592 /*******************************************************************/
1593 /* dump analysis information that is expressed in graph terms. */
1594 /*******************************************************************/
1596 /* dump out edges */
1598 dump_out_edge(ir_node *n, void *env) {
1601 for (i = 0; i < get_irn_n_outs(n); i++) {
1602 assert(get_irn_out(n, i));
1603 fprintf (F, "edge: {sourcename: \"");
1605 fprintf (F, "\" targetname: \"");
1606 PRINT_NODEID(get_irn_out(n, i));
1607 fprintf (F, "\" color: red linestyle: dashed");
1613 dump_loop_label(FILE *F, ir_loop *loop) {
1614 fprintf (F, "loop %d, %d sons, %d nodes",
1615 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1618 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1619 fprintf (F, " info1: \"");
1620 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1621 #if DEBUG_libfirm /* GL @@@ debug analyses */
1622 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1628 dump_loop_node(FILE *F, ir_loop *loop) {
1629 fprintf (F, "node: {title: \"");
1631 fprintf (F, "\" label: \"");
1632 dump_loop_label(F, loop);
1634 dump_loop_info(F, loop);
1640 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1642 fprintf (F, "edge: {sourcename: \"");
1644 fprintf (F, "\" targetname: \"");
1645 PRINT_NODEID(get_loop_node(loop, i));
1646 fprintf (F, "\" color: green");
1651 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1653 fprintf (F, "edge: {sourcename: \"");
1655 fprintf (F, "\" targetname: \"");
1656 PRINT_LOOPID(get_loop_son(loop, i));
1657 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1658 get_loop_element_pos(loop, get_loop_son(loop, i)));
1662 void dump_loops(FILE *F, ir_loop *loop) {
1664 /* dump this loop node */
1665 dump_loop_node(F, loop);
1667 /* dump edges to nodes in loop -- only if it is a real loop */
1668 if (get_loop_depth(loop) != 0) {
1669 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1670 dump_loop_node_edge(F, loop, i);
1673 for (i = 0; i < get_loop_n_sons(loop); i++) {
1674 dump_loops(F, get_loop_son(loop, i));
1675 dump_loop_son_edge(F, loop, i);
1680 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1681 ir_graph *rem = current_ir_graph;
1682 current_ir_graph = irg;
1684 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1686 current_ir_graph = rem;
1691 * dumps the VCG header
1694 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1703 if (!orientation) orientation = "bottom_to_top";
1707 "graph: { title: \"ir graph of %s\"\n"
1708 "display_edge_labels: %s\n"
1709 "layoutalgorithm: mindepth\n"
1710 "manhattan_edges: yes\n"
1711 "port_sharing: no\n"
1713 "classname 1: \"intrablock Data\"\n"
1714 "classname 16: \"interblock Data\"\n"
1715 "classname 2: \"Block\"\n"
1716 "classname 13: \"Control Flow\"\n"
1717 "classname 14: \"intrablock Memory\"\n"
1718 "classname 17: \"interblock Memory\"\n"
1719 "classname 15: \"Dominators\"\n"
1720 "classname 3: \"Entity type\"\n"
1721 "classname 4: \"Entity owner\"\n"
1722 "classname 5: \"Method Param\"\n"
1723 "classname 6: \"Method Res\"\n"
1724 "classname 7: \"Super\"\n"
1725 "classname 8: \"Union\"\n"
1726 "classname 9: \"Points-to\"\n"
1727 "classname 10: \"Array Element Type\"\n"
1728 "classname 11: \"Overwrites\"\n"
1729 "classname 12: \"Member\"\n"
1730 "infoname 1: \"Attribute\"\n"
1731 "infoname 2: \"Verification errors\"\n",
1732 name, label, orientation);
1734 /* don't use all, the range is too whith/black. */
1738 "colorentry 100: 0 0 0\n"
1739 "colorentry 101: 20 0 0\n"
1740 "colorentry 102: 40 0 0\n"
1741 "colorentry 103: 60 0 0\n"
1742 "colorentry 104: 80 0 0\n"
1743 "colorentry 105: 100 0 0\n"
1744 "colorentry 106: 120 0 0\n"
1745 "colorentry 107: 140 0 0\n"
1746 "colorentry 108: 150 0 0\n"
1747 "colorentry 109: 180 0 0\n"
1748 "colorentry 110: 200 0 0\n"
1749 "colorentry 111: 220 0 0\n"
1750 "colorentry 112: 240 0 0\n"
1751 "colorentry 113: 255 0 0\n"
1752 "colorentry 113: 255 20 20\n"
1753 "colorentry 114: 255 40 40\n"
1754 "colorentry 115: 255 60 60\n"
1755 "colorentry 116: 255 80 80\n"
1756 "colorentry 117: 255 100 100\n"
1757 "colorentry 118: 255 120 120\n"
1758 "colorentry 119: 255 140 140\n"
1759 "colorentry 120: 255 150 150\n"
1760 "colorentry 121: 255 180 180\n"
1761 "colorentry 122: 255 200 200\n"
1762 "colorentry 123: 255 220 220\n"
1763 "colorentry 124: 255 240 240\n"
1764 "colorentry 125: 255 250 250\n"
1767 fprintf (F, "\n"); /* a separator */
1773 * @param irg The graph to be dumped
1774 * @param suffix1 first filename suffix
1775 * @param suffix2 second filename suffix
1777 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1779 const char *nm = get_irg_dump_name(irg);
1780 int len = strlen(nm), i, j;
1781 char *fname; /* filename to put the vcg information in */
1783 if (!suffix1) suffix1 = "";
1784 if (!suffix2) suffix2 = "";
1786 /* open file for vcg graph */
1787 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1789 /* strncpy (fname, nm, len); */ /* copy the filename */
1791 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1793 fname[j] = '@'; j++; fname[j] = '1'; j++;
1794 } else if (nm[i] == '@') {
1795 fname[j] = '@'; j++; fname[j] = '2'; j++;
1797 fname[j] = nm[i]; j++;
1801 strcat (fname, suffix1); /* append file suffix */
1802 strcat (fname, suffix2); /* append file suffix */
1803 strcat (fname, ".vcg"); /* append the .vcg suffix */
1804 F = fopen (fname, "w"); /* open file for writing */
1806 panic("cannot open %s for writing (%m)", fname); /* not reached */
1816 * @param irg The graph to be dumped
1817 * @param suffix filename suffix
1819 static FILE *vcg_open_name (const char *name, const char *suffix) {
1821 char *fname; /* filename to put the vcg information in */
1822 int i, j, len = strlen(name);
1824 if (!suffix) suffix = "";
1826 /** open file for vcg graph */
1827 fname = malloc (len * 2 + 5 + strlen(suffix));
1828 /* strcpy (fname, name);*/ /* copy the filename */
1830 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1831 if (name[i] == '/') {
1832 fname[j] = '@'; j++; fname[j] = '1'; j++;
1833 } else if (name[i] == '@') {
1834 fname[j] = '@'; j++; fname[j] = '2'; j++;
1836 fname[j] = name[i]; j++;
1840 strcat (fname, suffix);
1841 strcat (fname, ".vcg"); /* append the .vcg suffix */
1842 F = fopen (fname, "w"); /* open file for writing */
1844 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1852 * Dumps the vcg file footer
1854 static INLINE void dump_vcg_footer (FILE *F) {
1859 * close the vcg file
1862 vcg_close (FILE *F) {
1863 dump_vcg_footer(F); /* print footer */
1864 fclose (F); /* close vcg file */
1867 /************************************************************************/
1868 /************************************************************************/
1869 /* Routines that dump all or parts of the firm representation to a file */
1870 /************************************************************************/
1871 /************************************************************************/
1873 /************************************************************************/
1874 /* Dump ir graphs, differnt formats and additional information. */
1875 /************************************************************************/
1877 /** Routine to dump a graph, blocks as conventional nodes.
1880 dump_ir_graph (ir_graph *irg, const char *suffix )
1885 rem = current_ir_graph;
1887 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1888 current_ir_graph = irg;
1889 if (interprocedural_view) suffix1 = "-pure-ip";
1890 else suffix1 = "-pure";
1891 f = vcg_open(irg, suffix, suffix1);
1892 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1894 /* walk over the graph */
1895 /* dump_whole_node must be called in post visiting predecessors */
1896 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1898 /* dump the out edges in a separate walk */
1899 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1900 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1905 current_ir_graph = rem;
1910 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1916 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1919 if (interprocedural_view) suffix1 = "-ip";
1921 f = vcg_open(irg, suffix, suffix1);
1922 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1924 construct_block_lists(irg);
1926 for (i = 0; i < get_irp_n_irgs(); i++) {
1927 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1929 dump_graph(f, get_irp_irg(i));
1937 /** dumps a graph with type information
1940 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1943 ir_graph *rem = current_ir_graph;
1946 /* if a filter is set, dump only the irg's that match the filter */
1947 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1950 current_ir_graph = irg;
1952 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1953 else suffix1 = "-pure-wtypes";
1954 f = vcg_open(irg,suffix, suffix1);
1955 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1957 /* dump common ir graph */
1958 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1959 /* dump type info */
1960 type_walk_irg(irg, dump_type_info, NULL, f);
1961 inc_irg_visited(get_const_code_irg());
1962 /* dump edges from graph to type info */
1963 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1966 current_ir_graph = rem;
1970 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1975 ir_graph *rem = current_ir_graph;
1977 /* if a filter is set, dump only the irg's that match the filter */
1978 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1981 if (interprocedural_view) suffix1 = "-wtypes-ip";
1982 else suffix1 = "-wtypes";
1983 f = vcg_open(irg, suffix, suffix1);
1984 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1986 /* dump common blocked ir graph */
1987 construct_block_lists(irg);
1989 for (i = 0; i < get_irp_n_irgs(); i++) {
1990 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1992 dump_graph(f, get_irp_irg(i));
1997 /* dump type info */
1998 current_ir_graph = irg;
1999 type_walk_irg(irg, dump_type_info, NULL, f);
2000 inc_irg_visited(get_const_code_irg());
2002 /* dump edges from graph to type info */
2003 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2005 current_ir_graph = rem;
2009 /*---------------------------------------------------------------------*/
2010 /* The following routines dump a control flow graph. */
2011 /*---------------------------------------------------------------------*/
2014 dump_block_to_cfg(ir_node *block, void *env) {
2019 if (is_Block(block)) {
2020 /* This is a block. Dump a node for the block. */
2021 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2022 fprintf (F, "\" label: \"");
2023 if (block == get_irg_start_block(get_irn_irg(block)))
2024 fprintf(F, "Start ");
2025 if (block == get_irg_end_block(get_irn_irg(block)))
2028 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2029 PRINT_NODEID(block);
2031 fprintf(F, "info1:\"");
2032 if (dump_dominator_information_flag)
2033 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2035 /* show arity and possible Bad predecessors of the block */
2036 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2037 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2038 ir_node *pred = get_Block_cfgpred(block, i);
2041 fprintf(F, "Bad pred at pos: ");
2042 fprintf(F, "%d ", i);
2049 fprintf (F, "\""); /* closing quote of info */
2051 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2052 (block == get_irg_end_block(get_irn_irg(block))) )
2053 fprintf(F, " color:blue ");
2055 fprintf(F, " color:yellow ");
2058 /* Dump the edges */
2059 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2060 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2061 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2062 fprintf (F, "edge: { sourcename: \"");
2063 PRINT_NODEID(block);
2064 fprintf (F, "\" targetname: \"");
2066 fprintf (F, "\"}\n");
2069 /* Dump dominator edge */
2070 if (dump_dominator_information_flag && get_Block_idom(block)) {
2071 pred = get_Block_idom(block);
2072 fprintf (F, "edge: { sourcename: \"");
2073 PRINT_NODEID(block);
2074 fprintf (F, "\" targetname: \"");
2076 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2082 dump_cfg (ir_graph *irg, const char *suffix)
2085 ir_graph *rem = current_ir_graph;
2086 int ddif = dump_dominator_information_flag;
2087 int ipv = interprocedural_view;
2089 /* if a filter is set, dump only the irg's that match the filter */
2090 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2093 current_ir_graph = irg;
2095 f = vcg_open(irg, suffix, "-cfg");
2096 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2098 if (interprocedural_view) {
2099 printf("Warning: dumping cfg not in interprocedural view!\n");
2100 interprocedural_view = 0;
2103 if (get_irg_dom_state(irg) != dom_consistent)
2104 dump_dominator_information_flag = 0;
2106 /* walk over the blocks in the graph */
2107 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2108 dump_node(f, get_irg_bad(irg));
2110 dump_dominator_information_flag = ddif;
2111 interprocedural_view = ipv;
2113 current_ir_graph = rem;
2116 static int weight_overall(int rec, int loop) {
2117 return 2*rec + loop;
2120 static int compute_color (int my, int max) {
2125 /* if small, scale to the full color range. */
2127 my = my * (n_colors/max);
2129 int step = 1 + (max / n_colors);
2133 return base_color + n_colors - color;
2136 static int get_entity_color(entity *ent) {
2137 assert(get_entity_irg(ent));
2138 ir_graph *irg = get_entity_irg(ent);
2140 int rec_depth = get_irg_recursion_depth(irg);
2141 int loop_depth = get_irg_loop_depth(irg);
2142 int overall_depth = weight_overall(rec_depth, loop_depth);
2144 int max_rec_depth = irp->max_callgraph_recursion_depth;
2145 int max_loop_depth = irp->max_callgraph_loop_depth;
2146 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2148 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2149 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2150 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2152 return my_overall_color;
2155 void dump_callgraph(const char *suffix) {
2157 int i, n_irgs = get_irp_n_irgs();
2158 int rem = edge_label;
2160 //ident *prefix = new_id_from_str("java/");
2162 F = vcg_open_name("Callgraph", suffix);
2163 dump_vcg_header(F, "Callgraph", NULL);
2165 for (i = 0; i < n_irgs; ++i) {
2166 ir_graph *irg = get_irp_irg(i);
2167 entity *ent = get_irg_entity(irg);
2168 int j, n_callees = get_irg_n_callees(irg);
2170 /* Do not dump runtime system. */
2171 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2173 dump_entity_node(F, ent, get_entity_color(ent));
2174 for (j = 0; j < n_callees; ++j) {
2175 entity *c = get_irg_entity(get_irg_callee(irg, j));
2176 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2177 int be = is_irg_callee_backedge(irg, j);
2180 "label:\"recursion %d\" color: %d" :
2181 "label:\"calls %d\" color: %d";
2182 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2190 /* Dump all irgs in interprocedural view to a single file. */
2191 void dump_all_cg_block_graph(const char *suffix) {
2194 int rem_view = interprocedural_view;
2195 interprocedural_view = 1;
2197 f = vcg_open_name("All_graphs", suffix);
2198 dump_vcg_header(f, "All_graphs", NULL);
2200 /* collect nodes in all irgs reachable in call graph*/
2201 for (i = 0; i < get_irp_n_irgs(); i++)
2202 ird_set_irg_link(get_irp_irg(i), NULL);
2204 cg_walk(clear_link, collect_node, NULL);
2206 /* dump all graphs */
2207 for (i = 0; i < get_irp_n_irgs(); i++) {
2208 current_ir_graph = get_irp_irg(i);
2209 assert(ird_get_irg_link(current_ir_graph));
2210 dump_graph(f, current_ir_graph);
2211 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2215 interprocedural_view = rem_view;
2218 /***********************************************************************/
2219 /* the following routines dumps type information without any ir nodes. */
2220 /***********************************************************************/
2223 dump_type_graph (ir_graph *irg, const char *suffix)
2227 rem = current_ir_graph;
2229 /* if a filter is set, dump only the irg's that match the filter */
2230 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2232 current_ir_graph = irg;
2234 f = vcg_open(irg, suffix, "-type");
2235 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2237 /* walk over the blocks in the graph */
2238 type_walk_irg(irg, dump_type_info, NULL, f);
2239 /* The walker for the const code can be called several times for the
2240 same (sub) experssion. So that no nodes are dumped several times
2241 we decrease the visited flag of the corresponding graph after each
2242 walk. So now increase it finally. */
2243 inc_irg_visited(get_const_code_irg());
2246 current_ir_graph = rem;
2250 dump_all_types (const char *suffix)
2252 FILE *f = vcg_open_name("All_types", suffix);
2253 dump_vcg_header(f, "All_types", NULL);
2254 type_walk(dump_type_info, NULL, f);
2255 inc_irg_visited(get_const_code_irg());
2260 dump_class_hierarchy (bool entities, const char *suffix)
2262 FILE *f = vcg_open_name("class_hierarchy", suffix);
2266 dump_vcg_header(f, "class_hierarchy", NULL);
2271 type_walk(dump_class_hierarchy_node, NULL, &env);
2275 /***********************************************************************/
2276 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2278 /* dump_ir_block_graph */
2280 /* dump_type_graph */
2281 /* dump_ir_graph_w_types */
2282 /***********************************************************************/
2284 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2285 int i, n_irgs = get_irp_n_irgs();
2286 for (i = 0; i < n_irgs; ++i) {
2287 dmp_grph(get_irp_irg(i), suffix);
2292 /**********************************************************************************
2293 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2294 * packed together in one subgraph/box *
2295 **********************************************************************************/
2297 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2298 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2300 ir_loop *son = NULL;
2302 /* Dump a new loop node. */
2303 dump_loop_node(F, loop);
2305 /* Dump the loop elements. */
2307 for(i = 0; i < get_loop_n_elements(loop); i++) {
2308 le = get_loop_element(loop, i);
2310 if (get_kind(son) == k_ir_loop) {
2312 /* We are a loop son -> Recurse */
2314 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2315 fprintf(F, "\" }\n");
2316 fprintf (F, "edge: {sourcename: \"");
2318 fprintf (F, "\" targetname: \"");
2320 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2321 loop_node_started = 0;
2323 dump_loop_son_edge(F, loop, son_number++);
2324 dump_loops_standalone(F, son);
2325 } else if (get_kind(son) == k_ir_node) {
2326 /* We are a loop node -> Collect firm nodes */
2328 ir_node *n = le.node;
2331 if (!loop_node_started) {
2332 /* Start a new node which contains all firm nodes of the current loop */
2333 fprintf (F, "node: { title: \"");
2335 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2336 loop_node_started = 1;
2342 bad |= dump_node_opcode(F, n);
2343 bad |= dump_node_mode(F, n);
2344 bad |= dump_node_typeinfo(F, n);
2346 bad |= dump_node_nodeattr(F, n);
2347 fprintf (F, " %ld", get_irn_node_nr(n));
2348 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2349 } else { /* for callgraph loop tree */
2350 assert(get_kind(son) == k_ir_graph);
2351 /* We are a loop node -> Collect firm graphs */
2352 ir_graph *n = (ir_graph *)le.node;
2353 if (!loop_node_started) {
2354 /* Start a new node which contains all firm nodes of the current loop */
2355 fprintf (F, "node: { title: \"");
2357 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2358 loop_node_started = 1;
2363 fprintf (F, " %s", get_irg_dump_name(n));
2364 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2368 if (loop_node_started) {
2369 fprintf(F, "\" }\n");
2370 fprintf (F, "edge: {sourcename: \"");
2372 fprintf (F, "\" targetname: \"");
2374 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2375 loop_node_started = 0;
2379 void dump_loop_tree(ir_graph *irg, const char *suffix)
2382 ir_graph *rem = current_ir_graph;
2383 int el_rem = edge_label;
2386 /* if a filter is set, dump only the irg's that match the filter */
2387 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2390 current_ir_graph = irg;
2392 f = vcg_open(irg, suffix, "-looptree");
2393 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2395 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2399 edge_label = el_rem;
2400 current_ir_graph = rem;
2403 void dump_callgraph_loop_tree(const char *suffix) {
2405 F = vcg_open_name("Callgraph_looptree", suffix);
2406 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2407 dump_loops_standalone(F, irp->outermost_cg_loop);
2412 /*******************************************************************************/
2413 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2414 /*******************************************************************************/
2416 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2417 int i, son_number = 0, node_number = 0;
2419 if (dump_loop_information_flag) dump_loop_node(F, loop);
2421 for (i = 0; i < get_loop_n_elements(loop); i++) {
2422 loop_element le = get_loop_element(loop, i);
2423 if (*(le.kind) == k_ir_loop) {
2424 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2426 collect_nodeloop(F, le.son, loopnodes);
2428 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2429 eset_insert(loopnodes, le.node);
2434 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2437 for(i = 0; i < get_loop_n_elements(loop); i++) {
2438 loop_element le = get_loop_element(loop, i);
2439 if (*(le.kind) == k_ir_loop) {
2441 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2443 if (is_Block(le.node)) start = 0; else start = -1;
2444 for (j = start; j < get_irn_arity(le.node); j++) {
2445 ir_node *pred = get_irn_n(le.node, j);
2446 if (!eset_contains(loopnodes, pred)) {
2447 eset_insert(extnodes, pred);
2448 if (!is_Block(pred)) {
2449 pred = get_nodes_block(pred);
2450 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2458 void dump_loop(ir_loop *l, const char *suffix) {
2461 eset *loopnodes = eset_create();
2462 eset *extnodes = eset_create();
2465 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2466 F = vcg_open_name (name, suffix);
2467 dump_vcg_header(F, name, NULL);
2469 /* collect all nodes to dump */
2470 collect_nodeloop(F, l, loopnodes);
2471 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2473 /* build block lists */
2474 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2475 set_irn_link(n, NULL);
2476 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2477 set_irn_link(n, NULL);
2478 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2480 b = get_nodes_block(n);
2481 set_irn_link(n, get_irn_link(b));
2484 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2486 b = get_nodes_block(n);
2487 set_irn_link(n, get_irn_link(b));
2491 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2493 fprintf(F, "graph: { title: \"");
2495 fprintf(F, "\" label: \"");
2496 dump_node_opcode(F, b);
2497 fprintf (F, " %ld", get_irn_node_nr(b));
2498 fprintf(F, "\" status:clustered color:yellow\n");
2500 /* dump the blocks edges */
2501 dump_ir_data_edges(F, b);
2503 /* dump the nodes that go into the block */
2504 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2505 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2507 overrule_nodecolor = NULL;
2508 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2511 /* Close the vcg information for the block */
2513 dump_const_node_local(F, b);
2516 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2518 fprintf(F, "graph: { title: \"");
2520 fprintf(F, "\" label: \"");
2521 dump_node_opcode(F, b);
2522 fprintf (F, " %ld", get_irn_node_nr(b));
2523 fprintf(F, "\" status:clustered color:lightblue\n");
2525 /* dump the nodes that go into the block */
2526 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2527 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2529 overrule_nodecolor = NULL;
2530 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2533 /* Close the vcg information for the block */
2535 dump_const_node_local(F, b);
2539 eset_destroy(loopnodes);
2540 eset_destroy(extnodes);