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_typeinfo_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");
804 fprintf(F, "SymConst of type %s \n", get_type_name_ex(get_SymConst_value_type(n), &bad));
808 if (interprocedural_view) {
809 fprintf(F, "intra predecessor nodes:\n");
810 for (i = 0; i < get_irn_intra_arity(n); i++) {
811 ir_node *pred = get_irn_intra_n(n, i);
812 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
815 fprintf(F, "inter predecessor nodes:\n");
816 for (i = 0; i < get_irn_inter_arity(n); i++) {
817 ir_node *pred = get_irn_inter_n(n, i);
818 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
819 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
824 fprintf(F, "volatility: %s\n", get_volatility_name(get_Load_volatility(n)));
827 fprintf(F, "volatility: %s\n", get_volatility_name(get_Store_volatility(n)));
833 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
834 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
835 if (get_irn_typeinfo_type(n) != none_type)
836 fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_typeinfo_type(n), &bad));
845 bool is_constlike_node(ir_node *n) {
846 ir_op *op = get_irn_op(n);
847 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
851 /* outputs the predecessors of n, that are constants, local. I.e.,
852 generates a copy of the constant predecessors for each node called with. */
853 static void dump_const_node_local(FILE *F, ir_node *n) {
855 if (!get_opt_dump_const_local()) return;
857 /* Use visited flag to avoid outputting nodes twice.
858 initialize it first. */
859 for (i = 0; i < get_irn_arity(n); i++) {
860 ir_node *con = get_irn_n(n, i);
861 if (is_constlike_node(con)) {
862 set_irn_visited(con, get_irg_visited(current_ir_graph) - 1);
866 for (i = 0; i < get_irn_arity(n); i++) {
867 ir_node *con = get_irn_n(n, i);
868 if (is_constlike_node(con) && irn_not_visited(con)) {
871 mark_irn_visited(con);
872 /* Generate a new name for the node by appending the names of
874 fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
875 fprintf(F, " label: \"");
876 bad |= dump_node_opcode(F, con);
877 bad |= dump_node_mode(F, con);
878 bad |= dump_node_typeinfo(F, con);
880 bad |= dump_node_nodeattr(F, con);
881 fprintf(F, " %ld", get_irn_node_nr(con));
883 bad |= dump_node_info(F, con);
884 dump_node_vcgattr(F, con, bad);
890 static void INLINE print_node_error(FILE *F, const char *p)
895 fprintf (F, " info2: \"%s\"", p);
898 static void dump_node(FILE *F, ir_node *n)
903 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
905 fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
907 bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
908 bad |= dump_node_opcode(F, n);
909 bad |= dump_node_mode(F, n);
910 bad |= dump_node_typeinfo(F, n);
912 bad |= dump_node_nodeattr(F, n);
913 fprintf(F, " %ld", get_irn_node_nr(n));
915 bad |= dump_node_info(F, n);
916 print_node_error(F, p);
917 dump_node_vcgattr(F, n, bad);
919 dump_const_node_local(F, n);
926 /* dump the edge to the block this node belongs to */
928 dump_ir_block_edge(FILE *F, ir_node *n) {
929 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
930 if (is_no_Block(n)) {
931 ir_node *block = get_nodes_block(n);
933 fprintf (F, "edge: { sourcename: \"");
935 fprintf (F, "\" targetname: ");
936 fprintf(F, "\""); PRINT_NODEID(block); fprintf(F, "\"");
937 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
942 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
943 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
944 fprintf (F, INTRA_DATA_EDGE_ATTR);
946 fprintf (F, INTER_DATA_EDGE_ATTR);
950 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
951 if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
952 fprintf (F, INTRA_MEM_EDGE_ATTR);
954 fprintf (F, INTER_MEM_EDGE_ATTR);
958 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
961 if (dump_backedge_information_flag && is_backedge(from, to))
962 fprintf (F, BACK_EDGE_ATTR);
964 switch (get_irn_opcode(from)) {
966 fprintf (F, CF_EDGE_ATTR);
968 case iro_Start: break;
971 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
972 fprintf (F, CF_EDGE_ATTR);
973 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
974 fprintf (F, INTER_MEM_EDGE_ATTR);
982 print_data_edge_vcgattr(F, from, to);
987 print_mem_edge_vcgattr(F, from, to);
989 print_data_edge_vcgattr(F, from, to);
993 print_data_edge_vcgattr(F, from, to);
998 print_mem_edge_vcgattr(F, from, to);
1000 print_data_edge_vcgattr(F, from, to);
1007 print_data_edge_vcgattr(F, from, to);
1014 print_mem_edge_vcgattr(F, from, to);
1016 print_data_edge_vcgattr(F, from, to);
1028 print_data_edge_vcgattr(F, from, to);
1031 if (get_irn_modecode(from) == irm_M)
1032 fprintf (F, INTER_MEM_EDGE_ATTR);
1034 print_data_edge_vcgattr(F, from, to);
1041 print_mem_edge_vcgattr(F, from, to);
1043 print_data_edge_vcgattr(F, from, to);
1046 print_mem_edge_vcgattr(F, from, to);
1048 case iro_Tuple: break;
1051 switch (get_irn_modecode(from)) {
1053 fprintf (F, CF_EDGE_ATTR);
1056 fprintf (F, INTER_MEM_EDGE_ATTR);
1059 print_data_edge_vcgattr(F, from, to);
1063 case iro_Bad: break;
1064 case iro_Unknown: break;
1066 switch (get_irn_modecode(from)) {
1068 fprintf (F, INTRA_MEM_EDGE_ATTR);
1071 fprintf (F, CF_EDGE_ATTR);
1074 print_data_edge_vcgattr(F, from, to);
1082 /* dump edges to our inputs */
1084 dump_ir_data_edges(FILE *F, ir_node *n) {
1085 int i, visited = get_irn_visited(n);
1087 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1090 for (i = 0; i < get_irn_arity(n); i++) {
1091 ir_node * pred = get_irn_n(n, i);
1094 if ((interprocedural_view && get_irn_visited(pred) < visited))
1095 continue; /* pred not dumped */
1097 if (dump_backedge_information_flag && is_backedge(n, i))
1098 fprintf (F, "backedge: {sourcename: \"");
1100 fprintf (F, "edge: {sourcename: \"");
1102 fprintf (F, "\" targetname: ");
1103 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1104 PRINT_CONSTID(n, pred);
1106 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1108 fprintf (F, " label: \"%d\" ", i);
1109 print_edge_vcgattr(F, n, i);
1114 /** Dumps a node and its edges but not the block edge
1117 dump_node_wo_blockedge (ir_node *n, void *env) {
1120 dump_ir_data_edges(F, n);
1123 /** Dumps a node and its edges.
1126 dump_whole_node (ir_node *n, void *env) {
1128 dump_node_wo_blockedge(n, env);
1129 if (!node_floats(n)) dump_ir_block_edge(F, n);
1133 dump_const_node(ir_node *n, void *env) {
1134 if (is_Block(n)) return;
1135 dump_node_wo_blockedge(n, env);
1138 /***********************************************************************/
1139 /* the following routines dump the nodes/irgs bracketed to graphs. */
1140 /***********************************************************************/
1142 /** Dumps a constant expression as entity initializer, array bound ...
1144 static void dump_const_expression(FILE *F, ir_node *value) {
1145 ir_graph *rem = current_ir_graph;
1146 int rem_dump_const_local = dump_const_local;
1147 dump_const_local = 0;
1148 current_ir_graph = get_const_code_irg();
1149 irg_walk(value, dump_const_node, NULL, F);
1150 /* Decrease visited flag so that we walk with the same flag for the next
1151 expresssion. This guarantees that we don't dump the same node twice,
1152 as for const expressions cse is performed to save memory. */
1153 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1154 current_ir_graph = rem;
1155 dump_const_local = rem_dump_const_local;
1158 /** Dump a block as graph containing its nodes.
1160 * Expects to find nodes belonging to the block as list in its
1162 * Dumps the edges of all nodes including itself. */
1164 dump_whole_block(FILE *F, ir_node *block) {
1166 assert(is_Block(block));
1168 fprintf(F, "graph: { title: \"");
1169 PRINT_NODEID(block);
1170 fprintf(F, "\" label: \"");
1171 dump_node_opcode(F, block);
1172 fprintf (F, " %ld", get_irn_node_nr(block));
1174 if (get_opt_dump_abstvals())
1175 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1177 fprintf(F, "\" status:clustered color:%s \n",
1178 get_Block_matured(block) ? "yellow" : "red");
1180 /* dump the blocks edges */
1181 dump_ir_data_edges(F, block);
1183 /* dump the nodes that go into the block */
1184 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1186 dump_ir_data_edges(F, node);
1189 /* Close the vcg information for the block */
1191 dump_const_node_local(F, block);
1193 dump_chi_term(F, block);
1198 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1199 * The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1201 dump_block_graph(FILE *F, ir_graph *irg) {
1203 ir_graph *rem = current_ir_graph;
1204 ir_node **arr = ird_get_irg_link(irg);
1205 current_ir_graph = irg;
1207 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1208 ir_node * node = arr[i];
1209 if (is_Block(node)) {
1210 /* Dumps the block and all the nodes in the block, which are to
1211 be found in Block->link. */
1212 dump_whole_block(F, node);
1214 /* Nodes that are not in a Block. */
1216 dump_ir_data_edges(F, node);
1220 if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
1221 dump_loop_nodes_into_graph(F, irg);
1223 current_ir_graph = rem;
1226 /** Dumps an irg as a graph.
1227 * If interprocedural view edges can point to nodes out of this graph.
1229 static void dump_graph(FILE *F, ir_graph *irg) {
1231 fprintf(F, "graph: { title: \"");
1233 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1234 get_ent_dump_name(get_irg_entity(irg)));
1236 dump_block_graph(F, irg);
1238 /* Close the vcg information for the irg */
1239 fprintf(F, "}\n\n");
1242 /*******************************************************************/
1243 /* Basic type and entity nodes and edges. */
1244 /*******************************************************************/
1246 /* dumps the edges between nodes and their type or entity attributes. */
1247 static void dump_node2type_edges(ir_node *n, void *env)
1252 switch (get_irn_opcode(n)) {
1254 /* @@@ some consts have an entity */
1257 if ( (get_SymConst_kind(n) ==symconst_type_tag)
1258 || (get_SymConst_kind(n) ==symconst_size))
1260 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1264 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1267 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1270 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1273 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1276 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1284 static int print_type_info(FILE *F, type *tp) {
1287 if (get_type_state(tp) == layout_undefined) {
1288 fprintf(F, "state: layout_undefined\n");
1290 fprintf(F, "state: layout_fixed,\n");
1292 if (get_type_mode(tp))
1293 fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1294 fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1299 static void print_typespecific_info(FILE *F, type *tp) {
1300 switch (get_type_tpop_code(tp)) {
1303 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1310 fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1311 fprintf(F, "params: %d\n", get_method_n_params(tp));
1312 fprintf(F, "results: %d\n", get_method_n_ress(tp));
1320 case tpo_enumeration:
1334 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1335 switch (get_type_tpop_code(tp)) {
1338 if (peculiarity_existent == get_class_peculiarity(tp))
1339 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1341 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1345 fprintf (F, " " TYPE_METH_NODE_ATTR);
1356 case tpo_enumeration:
1369 static int print_type_node(FILE *F, type *tp)
1373 fprintf (F, "node: {title: ");
1375 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1376 fprintf (F, " info1: \"");
1377 bad |= print_type_info(F, tp);
1378 print_typespecific_info(F, tp);
1380 print_typespecific_vcgattr(F, tp);
1386 #define X(a) case a: fprintf(F, #a); break
1387 void dump_entity_node(FILE *F, entity *ent, int color)
1389 fprintf (F, "node: {title: \"");
1390 PRINT_ENTID(ent); fprintf(F, "\"");
1391 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1392 fprintf (F, "label: ");
1393 fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent));
1395 fprintf(F, "color: %d", color);
1397 fprintf (F, ENTITY_NODE_ATTR);
1398 fprintf (F, "\n info1: \"");
1400 dump_entity_to_file(F, ent, dump_verbosity_entattrs | dump_verbosity_entconsts);
1402 fprintf(F, "\"\n}\n");
1406 static void dump_enum_item(FILE *F, type *tp, int pos)
1409 ident *id = get_enumeration_nameid(tp, pos);
1410 tarval *tv = get_enumeration_enum(tp, pos);
1412 tarval_snprintf(buf, sizeof(buf), tv);
1413 fprintf (F, "node: {title: \"");
1414 PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1415 fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1416 fprintf (F, "label: ");
1417 fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1418 fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1421 /* dumps a type or entity and it's edges. */
1423 dump_type_info(type_or_ent *tore, void *env) {
1425 int i = 0; /* to shutup gcc */
1427 /* dump this type or entity */
1429 switch (get_kind(tore)) {
1432 entity *ent = (entity *)tore;
1435 dump_entity_node(F, ent, 0);
1437 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1438 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1439 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1440 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1441 if(is_class_type(get_entity_owner(ent))) {
1442 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1443 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1445 /* attached subgraphs */
1446 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1447 if (is_atomic_entity(ent)) {
1448 value = get_atomic_ent_value(ent);
1450 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1451 /* DDMN(value); $$$ */
1452 dump_const_expression(F, value);
1455 if (is_compound_entity(ent)) {
1456 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1457 value = get_compound_ent_value(ent, i);
1459 print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1460 dump_const_expression(F, value);
1461 print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1463 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1464 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1465 get_compound_ent_value_member(ent, i), i);
1474 type *tp = (type *)tore;
1475 print_type_node(F, tp);
1476 /* and now the edges */
1477 switch (get_type_tpop_code(tp)) {
1480 for (i=0; i < get_class_n_supertypes(tp); i++)
1481 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1482 for (i=0; i < get_class_n_members(tp); i++)
1483 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1487 for (i=0; i < get_struct_n_members(tp); i++)
1488 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1492 for (i = 0; i < get_method_n_params(tp); i++)
1493 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1494 for (i = 0; i < get_method_n_ress(tp); i++)
1495 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1499 for (i = 0; i < get_union_n_members(tp); i++)
1500 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1504 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1505 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1506 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1507 ir_node *upper = get_array_upper_bound(tp, i);
1508 ir_node *lower = get_array_lower_bound(tp, i);
1509 print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1510 print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1511 dump_const_expression(F, upper);
1512 dump_const_expression(F, lower);
1516 case tpo_enumeration:
1518 for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1519 dump_enum_item(F, tp, i);
1520 print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1525 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1533 break; /* case k_type */
1536 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1538 } /* switch kind_or_entity */
1541 typedef struct _h_env {
1546 /** For dumping class hierarchies.
1547 * Dumps a class type node and a superclass edge.
1548 * If env->dump_ent dumps entities of classes and overwrites edges.
1551 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1554 int i = 0; /* to shutup gcc */
1556 /* dump this type or entity */
1557 switch (get_kind(tore)) {
1559 entity *ent = (entity *)tore;
1560 if (get_entity_owner(ent) == get_glob_type()) break;
1561 if (!is_method_type(get_entity_type(ent))) break; /* GL */
1562 if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1564 dump_entity_node(F, ent, 0);
1566 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1567 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1568 print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1570 } break; /* case k_entity */
1573 type *tp = (type *)tore;
1574 if (tp == get_glob_type()) break;
1575 switch (get_type_tpop_code(tp)) {
1577 print_type_node(F, tp);
1578 /* and now the edges */
1579 for (i=0; i < get_class_n_supertypes(tp); i++)
1581 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1587 break; /* case k_type */
1590 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1592 } /* switch kind_or_entity */
1595 /*******************************************************************/
1596 /* dump analysis information that is expressed in graph terms. */
1597 /*******************************************************************/
1599 /* dump out edges */
1601 dump_out_edge(ir_node *n, void *env) {
1604 for (i = 0; i < get_irn_n_outs(n); i++) {
1605 assert(get_irn_out(n, i));
1606 fprintf (F, "edge: {sourcename: \"");
1608 fprintf (F, "\" targetname: \"");
1609 PRINT_NODEID(get_irn_out(n, i));
1610 fprintf (F, "\" color: red linestyle: dashed");
1616 dump_loop_label(FILE *F, ir_loop *loop) {
1617 fprintf (F, "loop %d, %d sons, %d nodes",
1618 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1621 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1622 fprintf (F, " info1: \"");
1623 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1624 #if DEBUG_libfirm /* GL @@@ debug analyses */
1625 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1631 dump_loop_node(FILE *F, ir_loop *loop) {
1632 fprintf (F, "node: {title: \"");
1634 fprintf (F, "\" label: \"");
1635 dump_loop_label(F, loop);
1637 dump_loop_info(F, loop);
1643 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1645 fprintf (F, "edge: {sourcename: \"");
1647 fprintf (F, "\" targetname: \"");
1648 PRINT_NODEID(get_loop_node(loop, i));
1649 fprintf (F, "\" color: green");
1654 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1656 fprintf (F, "edge: {sourcename: \"");
1658 fprintf (F, "\" targetname: \"");
1659 PRINT_LOOPID(get_loop_son(loop, i));
1660 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1661 get_loop_element_pos(loop, get_loop_son(loop, i)));
1665 void dump_loops(FILE *F, ir_loop *loop) {
1667 /* dump this loop node */
1668 dump_loop_node(F, loop);
1670 /* dump edges to nodes in loop -- only if it is a real loop */
1671 if (get_loop_depth(loop) != 0) {
1672 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1673 dump_loop_node_edge(F, loop, i);
1676 for (i = 0; i < get_loop_n_sons(loop); i++) {
1677 dump_loops(F, get_loop_son(loop, i));
1678 dump_loop_son_edge(F, loop, i);
1683 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1684 ir_graph *rem = current_ir_graph;
1685 current_ir_graph = irg;
1687 if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1689 current_ir_graph = rem;
1694 * dumps the VCG header
1697 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1706 if (!orientation) orientation = "bottom_to_top";
1710 "graph: { title: \"ir graph of %s\"\n"
1711 "display_edge_labels: %s\n"
1712 "layoutalgorithm: mindepth\n"
1713 "manhattan_edges: yes\n"
1714 "port_sharing: no\n"
1716 "classname 1: \"intrablock Data\"\n"
1717 "classname 16: \"interblock Data\"\n"
1718 "classname 2: \"Block\"\n"
1719 "classname 13: \"Control Flow\"\n"
1720 "classname 14: \"intrablock Memory\"\n"
1721 "classname 17: \"interblock Memory\"\n"
1722 "classname 15: \"Dominators\"\n"
1723 "classname 3: \"Entity type\"\n"
1724 "classname 4: \"Entity owner\"\n"
1725 "classname 5: \"Method Param\"\n"
1726 "classname 6: \"Method Res\"\n"
1727 "classname 7: \"Super\"\n"
1728 "classname 8: \"Union\"\n"
1729 "classname 9: \"Points-to\"\n"
1730 "classname 10: \"Array Element Type\"\n"
1731 "classname 11: \"Overwrites\"\n"
1732 "classname 12: \"Member\"\n"
1733 "infoname 1: \"Attribute\"\n"
1734 "infoname 2: \"Verification errors\"\n",
1735 name, label, orientation);
1737 /* don't use all, the range is too whith/black. */
1741 "colorentry 100: 0 0 0\n"
1742 "colorentry 101: 20 0 0\n"
1743 "colorentry 102: 40 0 0\n"
1744 "colorentry 103: 60 0 0\n"
1745 "colorentry 104: 80 0 0\n"
1746 "colorentry 105: 100 0 0\n"
1747 "colorentry 106: 120 0 0\n"
1748 "colorentry 107: 140 0 0\n"
1749 "colorentry 108: 150 0 0\n"
1750 "colorentry 109: 180 0 0\n"
1751 "colorentry 110: 200 0 0\n"
1752 "colorentry 111: 220 0 0\n"
1753 "colorentry 112: 240 0 0\n"
1754 "colorentry 113: 255 0 0\n"
1755 "colorentry 113: 255 20 20\n"
1756 "colorentry 114: 255 40 40\n"
1757 "colorentry 115: 255 60 60\n"
1758 "colorentry 116: 255 80 80\n"
1759 "colorentry 117: 255 100 100\n"
1760 "colorentry 118: 255 120 120\n"
1761 "colorentry 119: 255 140 140\n"
1762 "colorentry 120: 255 150 150\n"
1763 "colorentry 121: 255 180 180\n"
1764 "colorentry 122: 255 200 200\n"
1765 "colorentry 123: 255 220 220\n"
1766 "colorentry 124: 255 240 240\n"
1767 "colorentry 125: 255 250 250\n"
1770 fprintf (F, "\n"); /* a separator */
1776 * @param irg The graph to be dumped
1777 * @param suffix1 first filename suffix
1778 * @param suffix2 second filename suffix
1780 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1782 const char *nm = get_irg_dump_name(irg);
1783 int len = strlen(nm), i, j;
1784 char *fname; /* filename to put the vcg information in */
1786 if (!suffix1) suffix1 = "";
1787 if (!suffix2) suffix2 = "";
1789 /* open file for vcg graph */
1790 fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1792 /* strncpy (fname, nm, len); */ /* copy the filename */
1794 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1796 fname[j] = '@'; j++; fname[j] = '1'; j++;
1797 } else if (nm[i] == '@') {
1798 fname[j] = '@'; j++; fname[j] = '2'; j++;
1800 fname[j] = nm[i]; j++;
1804 strcat (fname, suffix1); /* append file suffix */
1805 strcat (fname, suffix2); /* append file suffix */
1806 strcat (fname, ".vcg"); /* append the .vcg suffix */
1807 F = fopen (fname, "w"); /* open file for writing */
1809 panic("cannot open %s for writing (%m)", fname); /* not reached */
1819 * @param irg The graph to be dumped
1820 * @param suffix filename suffix
1822 static FILE *vcg_open_name (const char *name, const char *suffix) {
1824 char *fname; /* filename to put the vcg information in */
1825 int i, j, len = strlen(name);
1827 if (!suffix) suffix = "";
1829 /** open file for vcg graph */
1830 fname = malloc (len * 2 + 5 + strlen(suffix));
1831 /* strcpy (fname, name);*/ /* copy the filename */
1833 for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */
1834 if (name[i] == '/') {
1835 fname[j] = '@'; j++; fname[j] = '1'; j++;
1836 } else if (name[i] == '@') {
1837 fname[j] = '@'; j++; fname[j] = '2'; j++;
1839 fname[j] = name[i]; j++;
1843 strcat (fname, suffix);
1844 strcat (fname, ".vcg"); /* append the .vcg suffix */
1845 F = fopen (fname, "w"); /* open file for writing */
1847 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1855 * Dumps the vcg file footer
1857 static INLINE void dump_vcg_footer (FILE *F) {
1862 * close the vcg file
1865 vcg_close (FILE *F) {
1866 dump_vcg_footer(F); /* print footer */
1867 fclose (F); /* close vcg file */
1870 /************************************************************************/
1871 /************************************************************************/
1872 /* Routines that dump all or parts of the firm representation to a file */
1873 /************************************************************************/
1874 /************************************************************************/
1876 /************************************************************************/
1877 /* Dump ir graphs, differnt formats and additional information. */
1878 /************************************************************************/
1880 /** Routine to dump a graph, blocks as conventional nodes.
1883 dump_ir_graph (ir_graph *irg, const char *suffix )
1888 rem = current_ir_graph;
1890 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
1891 current_ir_graph = irg;
1892 if (interprocedural_view) suffix1 = "-pure-ip";
1893 else suffix1 = "-pure";
1894 f = vcg_open(irg, suffix, suffix1);
1895 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1897 /* walk over the graph */
1898 /* dump_whole_node must be called in post visiting predecessors */
1899 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1901 /* dump the out edges in a separate walk */
1902 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1903 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1908 current_ir_graph = rem;
1913 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1919 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1922 if (interprocedural_view) suffix1 = "-ip";
1924 f = vcg_open(irg, suffix, suffix1);
1925 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1927 construct_block_lists(irg);
1929 for (i = 0; i < get_irp_n_irgs(); i++) {
1930 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1932 dump_graph(f, get_irp_irg(i));
1940 /** dumps a graph with type information
1943 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1946 ir_graph *rem = current_ir_graph;
1949 /* if a filter is set, dump only the irg's that match the filter */
1950 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1953 current_ir_graph = irg;
1955 if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1956 else suffix1 = "-pure-wtypes";
1957 f = vcg_open(irg,suffix, suffix1);
1958 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1960 /* dump common ir graph */
1961 irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1962 /* dump type info */
1963 type_walk_irg(irg, dump_type_info, NULL, f);
1964 inc_irg_visited(get_const_code_irg());
1965 /* dump edges from graph to type info */
1966 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1969 current_ir_graph = rem;
1973 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1978 ir_graph *rem = current_ir_graph;
1980 /* if a filter is set, dump only the irg's that match the filter */
1981 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1984 if (interprocedural_view) suffix1 = "-wtypes-ip";
1985 else suffix1 = "-wtypes";
1986 f = vcg_open(irg, suffix, suffix1);
1987 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1989 /* dump common blocked ir graph */
1990 construct_block_lists(irg);
1992 for (i = 0; i < get_irp_n_irgs(); i++) {
1993 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1995 dump_graph(f, get_irp_irg(i));
2000 /* dump type info */
2001 current_ir_graph = irg;
2002 type_walk_irg(irg, dump_type_info, NULL, f);
2003 inc_irg_visited(get_const_code_irg());
2005 /* dump edges from graph to type info */
2006 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
2008 current_ir_graph = rem;
2012 /*---------------------------------------------------------------------*/
2013 /* The following routines dump a control flow graph. */
2014 /*---------------------------------------------------------------------*/
2017 dump_block_to_cfg(ir_node *block, void *env) {
2022 if (is_Block(block)) {
2023 /* This is a block. Dump a node for the block. */
2024 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
2025 fprintf (F, "\" label: \"");
2026 if (block == get_irg_start_block(get_irn_irg(block)))
2027 fprintf(F, "Start ");
2028 if (block == get_irg_end_block(get_irn_irg(block)))
2031 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
2032 PRINT_NODEID(block);
2034 fprintf(F, "info1:\"");
2035 if (dump_dominator_information_flag)
2036 fprintf(F, "dom depth %d\n", get_Block_dom_depth(block));
2038 /* show arity and possible Bad predecessors of the block */
2039 fprintf(F, "arity: %d\n", get_Block_n_cfgpreds(block));
2040 for (fl = i = 0; i < get_Block_n_cfgpreds(block); ++i) {
2041 ir_node *pred = get_Block_cfgpred(block, i);
2044 fprintf(F, "Bad pred at pos: ");
2045 fprintf(F, "%d ", i);
2052 fprintf (F, "\""); /* closing quote of info */
2054 if ((block == get_irg_start_block(get_irn_irg(block))) ||
2055 (block == get_irg_end_block(get_irn_irg(block))) )
2056 fprintf(F, " color:blue ");
2058 fprintf(F, " color:yellow ");
2061 /* Dump the edges */
2062 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
2063 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
2064 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
2065 fprintf (F, "edge: { sourcename: \"");
2066 PRINT_NODEID(block);
2067 fprintf (F, "\" targetname: \"");
2069 fprintf (F, "\"}\n");
2072 /* Dump dominator edge */
2073 if (dump_dominator_information_flag && get_Block_idom(block)) {
2074 pred = get_Block_idom(block);
2075 fprintf (F, "edge: { sourcename: \"");
2076 PRINT_NODEID(block);
2077 fprintf (F, "\" targetname: \"");
2079 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
2085 dump_cfg (ir_graph *irg, const char *suffix)
2088 ir_graph *rem = current_ir_graph;
2089 int ddif = dump_dominator_information_flag;
2090 int ipv = interprocedural_view;
2092 /* if a filter is set, dump only the irg's that match the filter */
2093 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2096 current_ir_graph = irg;
2098 f = vcg_open(irg, suffix, "-cfg");
2099 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2101 if (interprocedural_view) {
2102 printf("Warning: dumping cfg not in interprocedural view!\n");
2103 interprocedural_view = 0;
2106 if (get_irg_dom_state(irg) != dom_consistent)
2107 dump_dominator_information_flag = 0;
2109 /* walk over the blocks in the graph */
2110 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
2111 dump_node(f, get_irg_bad(irg));
2113 dump_dominator_information_flag = ddif;
2114 interprocedural_view = ipv;
2116 current_ir_graph = rem;
2119 static int weight_overall(int rec, int loop) {
2120 return 2*rec + loop;
2123 static int compute_color (int my, int max) {
2128 /* if small, scale to the full color range. */
2130 my = my * (n_colors/max);
2132 int step = 1 + (max / n_colors);
2136 return base_color + n_colors - color;
2139 static int get_entity_color(entity *ent) {
2140 assert(get_entity_irg(ent));
2141 ir_graph *irg = get_entity_irg(ent);
2143 int rec_depth = get_irg_recursion_depth(irg);
2144 int loop_depth = get_irg_loop_depth(irg);
2145 int overall_depth = weight_overall(rec_depth, loop_depth);
2147 int max_rec_depth = irp->max_callgraph_recursion_depth;
2148 int max_loop_depth = irp->max_callgraph_loop_depth;
2149 int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth);
2151 /* int my_rec_color = compute_color(rec_depth, max_rec_depth); */
2152 /* int my_loop_color = compute_color(loop_depth, max_loop_depth); */
2153 int my_overall_color = compute_color(overall_depth, max_overall_depth);;
2155 return my_overall_color;
2158 void dump_callgraph(const char *suffix) {
2160 int i, n_irgs = get_irp_n_irgs();
2161 int rem = edge_label;
2163 //ident *prefix = new_id_from_str("java/");
2165 F = vcg_open_name("Callgraph", suffix);
2166 dump_vcg_header(F, "Callgraph", NULL);
2168 for (i = 0; i < n_irgs; ++i) {
2169 ir_graph *irg = get_irp_irg(i);
2170 entity *ent = get_irg_entity(irg);
2171 int j, n_callees = get_irg_n_callees(irg);
2173 /* Do not dump runtime system. */
2174 //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
2176 dump_entity_node(F, ent, get_entity_color(ent));
2177 for (j = 0; j < n_callees; ++j) {
2178 entity *c = get_irg_entity(get_irg_callee(irg, j));
2179 //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
2180 int be = is_irg_callee_backedge(irg, j);
2183 "label:\"recursion %d\" color: %d" :
2184 "label:\"calls %d\" color: %d";
2185 print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
2193 /* Dump all irgs in interprocedural view to a single file. */
2194 void dump_all_cg_block_graph(const char *suffix) {
2197 int rem_view = interprocedural_view;
2198 interprocedural_view = 1;
2200 f = vcg_open_name("All_graphs", suffix);
2201 dump_vcg_header(f, "All_graphs", NULL);
2203 /* collect nodes in all irgs reachable in call graph*/
2204 for (i = 0; i < get_irp_n_irgs(); i++)
2205 ird_set_irg_link(get_irp_irg(i), NULL);
2207 cg_walk(clear_link, collect_node, NULL);
2209 /* dump all graphs */
2210 for (i = 0; i < get_irp_n_irgs(); i++) {
2211 current_ir_graph = get_irp_irg(i);
2212 assert(ird_get_irg_link(current_ir_graph));
2213 dump_graph(f, current_ir_graph);
2214 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2218 interprocedural_view = rem_view;
2221 /***********************************************************************/
2222 /* the following routines dumps type information without any ir nodes. */
2223 /***********************************************************************/
2226 dump_type_graph (ir_graph *irg, const char *suffix)
2230 rem = current_ir_graph;
2232 /* if a filter is set, dump only the irg's that match the filter */
2233 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2235 current_ir_graph = irg;
2237 f = vcg_open(irg, suffix, "-type");
2238 dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2240 /* walk over the blocks in the graph */
2241 type_walk_irg(irg, dump_type_info, NULL, f);
2242 /* The walker for the const code can be called several times for the
2243 same (sub) experssion. So that no nodes are dumped several times
2244 we decrease the visited flag of the corresponding graph after each
2245 walk. So now increase it finally. */
2246 inc_irg_visited(get_const_code_irg());
2249 current_ir_graph = rem;
2253 dump_all_types (const char *suffix)
2255 FILE *f = vcg_open_name("All_types", suffix);
2256 dump_vcg_header(f, "All_types", NULL);
2257 type_walk(dump_type_info, NULL, f);
2258 inc_irg_visited(get_const_code_irg());
2263 dump_class_hierarchy (bool entities, const char *suffix)
2265 FILE *f = vcg_open_name("class_hierarchy", suffix);
2269 dump_vcg_header(f, "class_hierarchy", NULL);
2274 type_walk(dump_class_hierarchy_node, NULL, &env);
2278 /***********************************************************************/
2279 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
2281 /* dump_ir_block_graph */
2283 /* dump_type_graph */
2284 /* dump_ir_graph_w_types */
2285 /***********************************************************************/
2287 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2288 int i, n_irgs = get_irp_n_irgs();
2289 for (i = 0; i < n_irgs; ++i) {
2290 dmp_grph(get_irp_irg(i), suffix);
2295 /**********************************************************************************
2296 * Dumps a stand alone loop graph with firm nodes which belong to one loop node *
2297 * packed together in one subgraph/box *
2298 **********************************************************************************/
2300 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2301 int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2303 ir_loop *son = NULL;
2305 /* Dump a new loop node. */
2306 dump_loop_node(F, loop);
2308 /* Dump the loop elements. */
2310 for(i = 0; i < get_loop_n_elements(loop); i++) {
2311 le = get_loop_element(loop, i);
2313 if (get_kind(son) == k_ir_loop) {
2315 /* We are a loop son -> Recurse */
2317 if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2318 fprintf(F, "\" }\n");
2319 fprintf (F, "edge: {sourcename: \"");
2321 fprintf (F, "\" targetname: \"");
2323 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2324 loop_node_started = 0;
2326 dump_loop_son_edge(F, loop, son_number++);
2327 dump_loops_standalone(F, son);
2328 } else if (get_kind(son) == k_ir_node) {
2329 /* We are a loop node -> Collect firm nodes */
2331 ir_node *n = le.node;
2334 if (!loop_node_started) {
2335 /* Start a new node which contains all firm nodes of the current loop */
2336 fprintf (F, "node: { title: \"");
2338 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2339 loop_node_started = 1;
2345 bad |= dump_node_opcode(F, n);
2346 bad |= dump_node_mode(F, n);
2347 bad |= dump_node_typeinfo(F, n);
2349 bad |= dump_node_nodeattr(F, n);
2350 fprintf (F, " %ld", get_irn_node_nr(n));
2351 if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2352 if (has_backedges(n)) fprintf(F, "\t loop head!");
2353 } else { /* for callgraph loop tree */
2354 assert(get_kind(son) == k_ir_graph);
2355 /* We are a loop node -> Collect firm graphs */
2356 ir_graph *n = (ir_graph *)le.node;
2357 if (!loop_node_started) {
2358 /* Start a new node which contains all firm nodes of the current loop */
2359 fprintf (F, "node: { title: \"");
2361 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2362 loop_node_started = 1;
2367 fprintf (F, " %s", get_irg_dump_name(n));
2368 /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2372 if (loop_node_started) {
2373 fprintf(F, "\" }\n");
2374 fprintf (F, "edge: {sourcename: \"");
2376 fprintf (F, "\" targetname: \"");
2378 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2379 loop_node_started = 0;
2383 void dump_loop_tree(ir_graph *irg, const char *suffix)
2386 ir_graph *rem = current_ir_graph;
2387 int el_rem = edge_label;
2390 /* if a filter is set, dump only the irg's that match the filter */
2391 if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2394 current_ir_graph = irg;
2396 f = vcg_open(irg, suffix, "-looptree");
2397 dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2399 if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2403 edge_label = el_rem;
2404 current_ir_graph = rem;
2407 void dump_callgraph_loop_tree(const char *suffix) {
2409 F = vcg_open_name("Callgraph_looptree", suffix);
2410 dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2411 dump_loops_standalone(F, irp->outermost_cg_loop);
2416 /*******************************************************************************/
2417 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2418 /*******************************************************************************/
2420 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2421 int i, son_number = 0, node_number = 0;
2423 if (dump_loop_information_flag) dump_loop_node(F, loop);
2425 for (i = 0; i < get_loop_n_elements(loop); i++) {
2426 loop_element le = get_loop_element(loop, i);
2427 if (*(le.kind) == k_ir_loop) {
2428 if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2430 collect_nodeloop(F, le.son, loopnodes);
2432 if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2433 eset_insert(loopnodes, le.node);
2438 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2441 for(i = 0; i < get_loop_n_elements(loop); i++) {
2442 loop_element le = get_loop_element(loop, i);
2443 if (*(le.kind) == k_ir_loop) {
2445 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2447 if (is_Block(le.node)) start = 0; else start = -1;
2448 for (j = start; j < get_irn_arity(le.node); j++) {
2449 ir_node *pred = get_irn_n(le.node, j);
2450 if (!eset_contains(loopnodes, pred)) {
2451 eset_insert(extnodes, pred);
2452 if (!is_Block(pred)) {
2453 pred = get_nodes_block(pred);
2454 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2462 void dump_loop(ir_loop *l, const char *suffix) {
2465 eset *loopnodes = eset_create();
2466 eset *extnodes = eset_create();
2469 snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2470 F = vcg_open_name (name, suffix);
2471 dump_vcg_header(F, name, NULL);
2473 /* collect all nodes to dump */
2474 collect_nodeloop(F, l, loopnodes);
2475 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2477 /* build block lists */
2478 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2479 set_irn_link(n, NULL);
2480 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2481 set_irn_link(n, NULL);
2482 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2484 b = get_nodes_block(n);
2485 set_irn_link(n, get_irn_link(b));
2488 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2490 b = get_nodes_block(n);
2491 set_irn_link(n, get_irn_link(b));
2495 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2497 fprintf(F, "graph: { title: \"");
2499 fprintf(F, "\" label: \"");
2500 dump_node_opcode(F, b);
2501 fprintf (F, " %ld", get_irn_node_nr(b));
2502 fprintf(F, "\" status:clustered color:yellow\n");
2504 /* dump the blocks edges */
2505 dump_ir_data_edges(F, b);
2507 /* dump the nodes that go into the block */
2508 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2509 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2511 overrule_nodecolor = NULL;
2512 if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2515 /* Close the vcg information for the block */
2517 dump_const_node_local(F, b);
2520 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2522 fprintf(F, "graph: { title: \"");
2524 fprintf(F, "\" label: \"");
2525 dump_node_opcode(F, b);
2526 fprintf (F, " %ld", get_irn_node_nr(b));
2527 fprintf(F, "\" status:clustered color:lightblue\n");
2529 /* dump the nodes that go into the block */
2530 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2531 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2533 overrule_nodecolor = NULL;
2534 if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2537 /* Close the vcg information for the block */
2539 dump_const_node_local(F, b);
2543 eset_destroy(loopnodes);
2544 eset_destroy(extnodes);