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.
22 # include "irnode_t.h"
23 # include "irgraph_t.h"
24 # include "entity_t.h"
26 # include "firm_common_t.h"
31 # include "typewalk.h"
34 # include "type_or_entity.h"
46 void dump_chi_term(FILE *FL, ir_node *n);
47 void dump_state(FILE *FL, ir_node *n);
48 int get_opt_dump_abstvals(void);
49 typedef unsigned long SeqNo;
50 SeqNo get_Block_seqno(ir_node *n);
53 /* Attributes of nodes */
54 #define PRINT_DEFAULT_NODE_ATTR
55 #define DEFAULT_NODE_ATTR " "
56 #define DEFAULT_TYPE_ATTRIBUTE " "
58 /* Attributes of edges between Firm nodes */
59 #define BLOCK_EDGE_ATTR "class:2 priority: 2 linestyle: dotted"
60 #define CF_EDGE_ATTR "class:13 color: red"
61 #define MEM_EDGE_ATTR "class:14 color: blue"
62 #define DOMINATOR_EDGE_ATTR "class:15 color: red"
64 #define BACK_EDGE_ATTR "linestyle: dashed "
66 /* Attributes of edges between Firm nodes and type/entity nodes */
67 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
69 /* Attributes of edges in type/entity graphs. */
70 #define TYPE_METH_NODE_ATTR "color: lightyellow"
71 #define TYPE_CLASS_NODE_ATTR "color: green"
72 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
73 #define ENTITY_NODE_ATTR "color: yellow"
74 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
75 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
76 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
77 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
78 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
79 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
80 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
81 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
82 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
83 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
84 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
85 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
86 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
89 #if DEBUG_libfirm && NODEID_AS_LABEL
90 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
91 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
92 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
93 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
94 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
95 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
98 #define PRINT_NODEID(X) fprintf(F, "n%p", (void*) X)
99 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *) X)
100 #define PRINT_ENTID(X) fprintf(F, "e%p", (void*) X)
101 #define PRINT_IRGID(X) fprintf(F, "g%p",(void*) X)
102 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*) X, (void*) Y)
103 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)X)
106 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
111 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
112 fprintf(F, " targetname: "); PRINT_TYPEID(T);
113 vfprintf(F, fmt, ap);
118 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
123 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
124 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
125 vfprintf(F, fmt, ap);
130 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
135 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
136 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
137 vfprintf(F, fmt, ap);
142 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
147 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
148 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
149 vfprintf(F, fmt, ap);
154 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
159 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
160 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
161 vfprintf(F, fmt, ap);
166 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
171 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
172 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
174 vfprintf(F, fmt, ap);
179 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
184 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
185 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
186 vfprintf(F, fmt, ap);
191 /*******************************************************************/
192 /* global and ahead declarations */
193 /*******************************************************************/
195 /* A suffix to manipulate the file name. */
196 char *dump_file_suffix = "";
198 char *dump_file_filter = "";
200 /* file to dump to */
203 static void dump_whole_node(ir_node *n, void* env);
204 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
206 /*******************************************************************/
207 /* Helper functions. */
208 /*******************************************************************/
210 /* Use private link attr to be able to call dumper anywhere without
211 destroying link fields. */
213 static pmap *irdump_link_map = NULL;
215 static void init_irdump(void) {
216 /* We need a new, empty map. */
217 if (irdump_link_map) pmap_destroy(irdump_link_map);
218 irdump_link_map = pmap_create();
222 void *ird_get_irn_link(ir_node *n) {
224 if (!irdump_link_map) return NULL;
226 if (pmap_contains(irdump_link_map, (void *)n))
227 res = pmap_get(irdump_link_map, (void *)n);
231 void ird_set_irn_link(ir_node *n, void *x) {
232 if (!irdump_link_map) init_irdump();
233 pmap_insert(irdump_link_map, (void *)n, x);
236 void *ird_get_irg_link(ir_graph *irg) {
238 if (!irdump_link_map) return NULL;
240 if (pmap_contains(irdump_link_map, (void *)irg))
241 res = pmap_get(irdump_link_map, (void *)irg);
245 void ird_set_irg_link(ir_graph *irg, void *x) {
246 if (!irdump_link_map) init_irdump();
247 pmap_insert(irdump_link_map, (void *)irg, x);
250 static void clear_link(ir_node * node, void * env) {
251 ird_set_irn_link(node, NULL);
255 static int node_floats(ir_node *n) {
256 return ((get_op_pinned(get_irn_op(n)) == floats) &&
257 (get_irg_pinned(current_ir_graph) == floats));
260 static const char *get_ent_dump_name (entity *ent) {
261 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
262 if (ent->ld_name) return get_id_str(ent->ld_name);
263 return get_id_str(ent->name);
266 static const char *get_irg_dump_name (ir_graph *irg) {
267 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
268 entity *ent = get_irg_ent(irg);
269 return get_ent_dump_name(ent);
272 static void collect_node(ir_node * node, void *env) {
275 || get_irn_op(node) == op_Bad
276 || get_irn_op(node) == op_Unknown) {
277 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
278 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
279 ARR_APP1(ir_node *, arr, node);
280 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
282 ir_node * block = get_nodes_block(node);
283 ird_set_irn_link(node, ird_get_irn_link(block));
284 ird_set_irn_link(block, node);
288 /** Construct lists to walk ir block-wise.
290 * Collects all blocks, nodes not pinned,
291 * Bad and Unknown into a flexible array in link field of
292 * irg they belong to. Sets the irg link field to NULL in all
293 * graphs not visited.
294 * Free the list with DEL_ARR_F. */
295 static ir_node ** construct_block_lists(ir_graph *irg) {
297 ir_graph *rem = current_ir_graph;
298 current_ir_graph = irg;
300 for (i = 0; i < get_irp_n_irgs(); i++)
301 ird_set_irg_link(get_irp_irg(i), NULL);
303 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
305 current_ir_graph = rem;
306 return ird_get_irg_link(irg);
309 /*******************************************************************/
310 /* flags to steer output */
311 /*******************************************************************/
313 /* A compiler option to turn off edge labels */
315 /* A compiler option to turn off dumping values of constant entities */
316 int const_entities = 1;
317 /* A compiler option to dump the keep alive edges */
318 int dump_keepalive = 0;
319 /* Compiler options to dump analysis information in dump_ir_graph */
320 int dump_out_edge_flag = 0;
321 int dump_dominator_information_flag = 0;
322 int dump_loop_information_flag = 0;
323 int dump_backedge_information_flag = 1;
324 int dump_const_local = 0;
325 bool opt_dump_analysed_type_info = 1;
326 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
328 char* overrule_nodecolor = NULL;
330 INLINE bool get_opt_dump_const_local(void) {
331 if (!dump_out_edge_flag && !dump_loop_information_flag)
332 return dump_const_local;
337 /* To turn off display of edge labels. Edge labels offen cause xvcg to
338 abort with a segmentation fault. */
339 void turn_off_edge_labels(void) {
343 void dump_consts_local(bool b) {
344 dump_const_local = b;
347 void turn_off_constant_entity_values(void) {
351 void dump_keepalive_edges(bool b) {
355 bool get_opt_dump_keepalive_edges(void) {
356 return dump_keepalive;
359 void dump_out_edges(void) {
360 dump_out_edge_flag = 1;
363 void dump_dominator_information(void) {
364 dump_dominator_information_flag = 1;
367 void dump_loop_information(void) {
368 dump_loop_information_flag = 1;
371 void dont_dump_loop_information(void) {
372 dump_loop_information_flag = 0;
375 void dump_backedge_information(bool b) {
376 dump_backedge_information_flag = b;
379 /* Dump the information of type field specified in ana/irtypeinfo.h.
380 * If the flag is set, the type name is output in [] in the node label,
381 * else it is output as info.
383 void dump_analysed_type_info(bool b) {
384 opt_dump_analysed_type_info = b;
387 void dump_pointer_values_to_info(bool b) {
388 opt_dump_pointer_values_to_info = b;
391 /*******************************************************************/
392 /* Routines to dump information about a single ir node. */
393 /*******************************************************************/
396 dump_node_opcode (ir_node *n)
399 switch(get_irn_opcode(n)) {
404 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
405 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
410 if (get_SymConst_kind(n) == linkage_ptr_info) {
411 /* don't use get_SymConst_ptr_info as it mangles the name. */
412 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
414 assert(get_kind(get_SymConst_type(n)) == k_type);
415 assert(get_type_ident(get_SymConst_type(n)));
416 fprintf (F, "SymC %s ", get_type_name(get_SymConst_type(n)));
417 if (get_SymConst_kind(n) == type_tag)
425 if (!interprocedural_view) fprintf(F, "Proj'");
426 else fprintf(F, "%s", get_irn_opname(n));
430 if (interprocedural_view) {
431 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
437 fprintf (F, "%s", get_irn_opname(n));
444 dump_node_mode (ir_node *n)
446 switch (get_irn_opcode(n)) {
465 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
472 static void dump_node_typeinfo(ir_node *n) {
473 if (!opt_dump_analysed_type_info) return;
474 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
475 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
476 type *tp = get_irn_type(n);
478 fprintf (F, " [%s]", get_type_name(tp));
485 dump_node_nodeattr (ir_node *n)
487 switch (get_irn_opcode(n)) {
489 if (false && interprocedural_view) {
490 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
494 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
495 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
497 fprintf (F, "%ld", get_Proj_proj(n));
501 fprintf (F, "%ld", get_Filter_proj(n));
504 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
507 fprintf (F, "(%s)", get_type_name(get_Cast_type(n)));
510 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
519 dump_node_vcgattr (ir_node *n)
521 switch (get_irn_opcode(n)) {
528 fprintf (F, "color: blue");
531 fprintf (F, "color: lightyellow");
534 fprintf (F, "color: green");
540 fprintf (F, "color: yellow");
543 PRINT_DEFAULT_NODE_ATTR;
546 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
550 dump_node_info (ir_node *n) {
554 fprintf (F, " info1: \"");
555 if (opt_dump_pointer_values_to_info)
556 fprintf (F, "addr: %p \n", (void *)n);
557 fprintf (F, "visited: %ld \n", get_irn_visited(n));
558 irg = get_irn_irg(n);
559 if (irg != get_const_code_irg())
560 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
562 fprintf(F, "arity: %d", get_irn_arity(n));
563 if ((get_irn_op(n) == op_Block) ||
564 (get_irn_op(n) == op_Phi) ||
565 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
566 fprintf(F, " backedges:");
568 for (i = 0; i < get_irn_arity(n); i++)
569 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
575 switch (get_irn_opcode(n)) {
577 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
578 fprintf(F, "start of method of type %s \n", get_type_name(tp));
579 for (i = 0; i < get_method_n_params(tp); ++i)
580 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
583 fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
586 fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
589 fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
590 fprintf(F, " from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
593 type *tp = get_Call_type(n);
594 fprintf(F, "calling method of type %s \n", get_type_name(tp));
595 for (i = 0; i < get_method_n_params(tp); ++i)
596 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
597 for (i = 0; i < get_method_n_ress(tp); ++i)
598 fprintf(F, " resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
599 if (Call_has_callees(n)) {
600 fprintf(F, "possible callees: \n");
601 for (i = 0; i < get_Call_n_callees(n); i++) {
602 if (!get_Call_callee(n, i)) {
603 fprintf(F, " %d external method\n", i);
605 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
610 case iro_CallBegin: {
611 ir_node *call = get_CallBegin_call(n);
612 if (Call_has_callees(call)) {
613 fprintf(F, "possible callees: \n");
614 for (i = 0; i < get_Call_n_callees(call); i++) {
615 if (!get_Call_callee(call, i)) {
616 fprintf(F, " %d external method\n", i);
618 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
624 if (!interprocedural_view) {
625 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
626 fprintf(F, "return in method of type %s \n", get_type_name(tp));
627 for (i = 0; i < get_method_n_ress(tp); ++i)
628 fprintf(F, " res %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
632 type *tp = get_Const_type(n);
633 assert(tp != none_type);
634 fprintf(F, "Const of type %s \n", get_type_name(get_Const_type(n)));
638 if (interprocedural_view) {
639 fprintf(F, "intra predecessor nodes:\n");
640 for (i = 0; i < get_irn_intra_arity(n); i++) {
641 ir_node *pred = get_irn_intra_n(n, i);
642 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
645 fprintf(F, "inter predecessor nodes:\n");
646 for (i = 0; i < get_irn_inter_arity(n); i++) {
647 ir_node *pred = get_irn_inter_n(n, i);
648 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
649 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
657 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
658 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
659 if (get_irn_type(n) != none_type)
660 fprintf (F, "\nAnalysed type: %s", get_type_name(get_irn_type(n)));
667 bool is_constlike_node(ir_node *n) {
668 ir_op *op = get_irn_op(n);
669 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
673 /* outputs the predecessors of n, that are constants, local. I.e.,
674 generates a copy of the constant predecessors for each node called with. */
675 static void dump_const_node_local(ir_node *n) {
677 if (!get_opt_dump_const_local()) return;
679 /* Use visited flag to avoid outputting nodes twice.
680 initialize it first. */
681 for (i = 0; i < get_irn_arity(n); i++) {
682 ir_node *con = get_irn_n(n, i);
683 if (is_constlike_node(con)) {
684 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
688 for (i = 0; i < get_irn_arity(n); i++) {
689 ir_node *con = get_irn_n(n, i);
690 if (is_constlike_node(con) && irn_not_visited(con)) {
691 mark_irn_visited(con);
692 /* Generate a new name for the node by appending the names of
694 fprintf (F, "node: {title: "); PRINT_CONSTID(n, con);
695 fprintf(F, " label: \"");
696 dump_node_opcode(con);
697 dump_node_mode (con);
698 dump_node_typeinfo(con);
700 dump_node_nodeattr(con);
701 fprintf (F, " %ld", get_irn_node_nr(con));
703 dump_node_vcgattr(con);
711 dump_node (ir_node *n) {
712 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
714 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
718 dump_node_typeinfo(n);
720 dump_node_nodeattr(n);
721 fprintf (F, " %ld", get_irn_node_nr(n));
723 dump_node_vcgattr(n);
726 dump_const_node_local(n);
733 /* dump the edge to the block this node belongs to */
735 dump_ir_block_edge(ir_node *n) {
736 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
737 if (is_no_Block(n)) {
738 fprintf (F, "edge: { sourcename: \"");
740 fprintf (F, "\" targetname: \"");
741 PRINT_NODEID(get_nodes_block(n));
742 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
746 static void print_edge_vcgattr(ir_node *from, int to) {
749 if (dump_backedge_information_flag && is_backedge(from, to))
750 fprintf (F, BACK_EDGE_ATTR);
752 switch (get_irn_opcode(from)) {
754 fprintf (F, CF_EDGE_ATTR);
756 case iro_Start: break;
759 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
760 fprintf (F, CF_EDGE_ATTR);
761 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
762 fprintf (F, MEM_EDGE_ATTR);
765 case iro_EndReg: break;
766 case iro_EndExcept: break;
768 case iro_Break: break;
769 case iro_Cond: break;
772 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
774 case iro_Const: break;
775 case iro_SymConst:break;
778 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
780 case iro_CallBegin: break;
783 case iro_Minus: break;
789 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
797 case iro_Shrs: break;
800 case iro_Conv: break;
802 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
808 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
811 fprintf (F, MEM_EDGE_ATTR);
813 case iro_Tuple: break;
816 switch (get_irn_modecode(from)) {
818 fprintf (F, CF_EDGE_ATTR);
821 fprintf (F, MEM_EDGE_ATTR);
827 case iro_Unknown: break;
834 /* dump edges to our inputs */
836 dump_ir_data_edges(ir_node *n) {
837 int i, visited = get_irn_visited(n);
839 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
842 for (i = 0; i < get_irn_arity(n); i++) {
843 ir_node * pred = get_irn_n(n, i);
846 if ((interprocedural_view && get_irn_visited(pred) < visited))
847 continue; /* pred not dumped */
849 if (dump_backedge_information_flag && is_backedge(n, i))
850 fprintf (F, "backedge: {sourcename: \"");
852 fprintf (F, "edge: {sourcename: \"");
854 fprintf (F, "\" targetname: ");
855 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
856 PRINT_CONSTID(n, pred);
858 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
860 fprintf (F, " label: \"%d\" ", i);
861 print_edge_vcgattr(n, i);
866 /** Dumps a node and its edges but not the block edge
869 dump_node_wo_blockedge (ir_node *n, void* env) {
871 dump_ir_data_edges(n);
874 /** Dumps a node and its edges.
877 dump_whole_node (ir_node *n, void* env) {
878 dump_node_wo_blockedge(n, env);
879 if (!node_floats(n)) dump_ir_block_edge(n);
883 dump_const_node(ir_node *n, void *env) {
884 if (is_Block(n)) return;
885 dump_node_wo_blockedge(n, env);
888 /***********************************************************************/
889 /* the following routines dump the nodes/irgs bracketed to graphs. */
890 /***********************************************************************/
892 /** Dumps a constant expression as entity initializer, array bound ...
894 static void dump_const_expression(ir_node *value) {
895 ir_graph *rem = current_ir_graph;
896 int rem_dump_const_local = dump_const_local;
897 dump_const_local = 0;
898 current_ir_graph = get_const_code_irg();
899 irg_walk(value, dump_const_node, NULL, NULL);
900 /* Decrease visited flag so that we walk with the same flag for the next
901 expresssion. This guarantees that we don't dump the same node twice,
902 as for const expressions cse is performed to save memory. */
903 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
904 current_ir_graph = rem;
905 dump_const_local = rem_dump_const_local;
908 /** Dump a block as graph containing its nodes.
910 * Expects to find nodes belonging to the block as list in its
912 * Dumps the edges of all nodes including itself. */
914 dump_whole_block(ir_node *block) {
916 assert(is_Block(block));
918 fprintf(F, "graph: { title: \"");
920 fprintf(F, "\" label: \"");
921 dump_node_opcode(block);
922 fprintf (F, " %ld", get_irn_node_nr(block));
924 if (get_opt_dump_abstvals())
925 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
927 fprintf(F, "\" status:clustered color:%s \n",
928 get_Block_matured(block) ? "yellow" : "red");
930 /* dump the blocks edges */
931 dump_ir_data_edges(block);
933 /* dump the nodes that go into the block */
934 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
936 dump_ir_data_edges(node);
939 /* Close the vcg information for the block */
941 dump_const_node_local(block);
943 dump_chi_term(F, block);
948 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
949 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
951 dump_block_graph (ir_graph *irg) {
953 ir_graph *rem = current_ir_graph;
954 ir_node **arr = ird_get_irg_link(irg);
955 current_ir_graph = irg;
957 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
958 ir_node * node = arr[i];
959 if (is_Block(node)) {
960 /* Dumps the block and all the nodes in the block, which are to
961 be found in Block->link. */
962 dump_whole_block(node);
964 /* Nodes that are not in a Block. */
966 dump_ir_data_edges(node);
970 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
972 current_ir_graph = rem;
975 /** Dumps an irg as a graph.
976 * If interprocedural view edges can point to nodes out of this graph.
978 static void dump_graph(ir_graph *irg) {
980 fprintf(F, "graph: { title: \"");
982 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
983 get_ent_dump_name(get_irg_ent(irg)));
985 dump_block_graph (irg);
987 /* Close the vcg information for the irg */
991 /*******************************************************************/
992 /* Basic type and entity nodes and edges. */
993 /*******************************************************************/
995 /* dumps the edges between nodes and their type or entity attributes. */
996 static void dump_node2type_edges (ir_node *n, void *env)
1000 switch (get_irn_opcode(n)) {
1002 /* @@@ some consts have an entity */
1005 if ( (get_SymConst_kind(n) == type_tag)
1006 || (get_SymConst_kind(n) == size))
1008 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1012 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1015 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1018 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1021 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1024 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1032 static void print_type_info(type *tp) {
1033 if (get_type_state(tp) == layout_undefined) {
1034 fprintf(F, "state: layout_undefined\n");
1036 fprintf(F, "state: layout_fixed,\n");
1038 if (get_type_mode(tp))
1039 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1040 fprintf(F, "size: %dB,\n", get_type_size(tp));
1043 static void print_typespecific_info(type *tp) {
1044 switch (get_type_tpop_code(tp)) {
1047 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1061 case tpo_enumeration:
1075 static void print_typespecific_vcgattr(type *tp) {
1076 switch (get_type_tpop_code(tp)) {
1079 if (peculiarity_existent == get_class_peculiarity(tp))
1080 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1082 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1086 fprintf (F, " " TYPE_METH_NODE_ATTR);
1097 case tpo_enumeration:
1110 static void print_type_node(type *tp)
1112 fprintf (F, "node: {title: ");
1114 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name(tp));
1115 fprintf (F, " info1: \"");
1116 print_type_info(tp);
1117 print_typespecific_info(tp);
1119 print_typespecific_vcgattr(tp);
1123 #define X(a) case a: fprintf(F, #a); break
1124 void dump_entity_node(entity *ent)
1126 fprintf (F, "node: {title: \"");
1127 PRINT_ENTID(ent); fprintf(F, "\"");
1128 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1129 fprintf (F, "label: ");
1130 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1131 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1133 fprintf (F, "\nallocation: ");
1134 switch (get_entity_allocation(ent)) {
1135 X(allocation_dynamic);
1136 X(allocation_automatic);
1137 X(allocation_static);
1138 X(allocation_parameter);
1141 fprintf (F, "\nvisibility: ");
1142 switch (get_entity_visibility(ent)) {
1143 X(visibility_local);
1144 X(visibility_external_visible);
1145 X(visibility_external_allocated);
1148 fprintf (F, "\nvariability: ");
1149 switch (get_entity_variability(ent)) {
1150 X(variability_uninitialized);
1151 X(variability_initialized);
1152 X(variability_part_constant);
1153 X(variability_constant);
1156 fprintf (F, "\nvolatility: ");
1157 switch (get_entity_volatility(ent)) {
1158 X(volatility_non_volatile);
1159 X(volatility_is_volatile);
1162 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1163 fprintf(F, "\nname: %s\nld_name: %s",
1164 get_ent_dump_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1165 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1166 if (is_method_type(get_entity_type(ent))) {
1167 if (get_entity_irg(ent)) /* can be null */
1168 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1170 { fprintf (F, "\nirg = NULL"); }
1172 fprintf(F, "\"\n}\n");
1176 /* dumps a type or entity and it's edges. */
1178 dump_type_info (type_or_ent *tore, void *env) {
1179 int i = 0; /* to shutup gcc */
1181 /* dump this type or entity */
1183 switch (get_kind(tore)) {
1186 entity *ent = (entity *)tore;
1189 dump_entity_node(ent);
1191 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1192 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1193 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1194 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1195 if(is_class_type(get_entity_owner(ent))) {
1196 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1197 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1200 /* attached subgraphs */
1201 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1202 if (is_atomic_entity(ent)) {
1203 value = get_atomic_ent_value(ent);
1205 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1206 /* DDMN(value); $$$ */
1207 dump_const_expression(value);
1210 if (is_compound_entity(ent)) {
1211 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1212 value = get_compound_ent_value(ent, i);
1214 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1215 dump_const_expression(value);
1216 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1218 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1219 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1220 get_compound_ent_value_member(ent, i), i);
1229 type *tp = (type *)tore;
1230 print_type_node(tp);
1231 /* and now the edges */
1232 switch (get_type_tpop_code(tp)) {
1235 for (i=0; i < get_class_n_supertypes(tp); i++) {
1236 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1239 for (i=0; i < get_class_n_members(tp); i++) {
1240 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1245 for (i=0; i < get_struct_n_members(tp); i++) {
1246 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1251 for (i = 0; i < get_method_n_params(tp); i++)
1253 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1255 for (i = 0; i < get_method_n_ress(tp); i++)
1257 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1262 for (i = 0; i < get_union_n_members(tp); i++)
1264 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1269 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1270 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1271 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1272 ir_node *upper = get_array_upper_bound(tp, i);
1273 ir_node *lower = get_array_lower_bound(tp, i);
1274 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1275 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1276 dump_const_expression(upper);
1277 dump_const_expression(lower);
1281 case tpo_enumeration:
1286 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1294 break; /* case k_type */
1297 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1299 } /* switch kind_or_entity */
1302 /** For dumping class hierarchies.
1303 * Dumps a class type node and a superclass edge.
1304 * If env != null dumps entities of classes and overwrites edges.
1307 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1308 int i = 0; /* to shutup gcc */
1310 /* dump this type or entity */
1311 switch (get_kind(tore)) {
1313 entity *ent = (entity *)tore;
1314 if (get_entity_owner(ent) == get_glob_type()) break;
1315 if ((env) && is_class_type(get_entity_owner(ent))) {
1317 dump_entity_node(ent);
1319 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1320 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1322 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1325 } break; /* case k_entity */
1328 type *tp = (type *)tore;
1329 if (tp == get_glob_type()) break;
1330 switch (get_type_tpop_code(tp)) {
1332 print_type_node(tp);
1333 /* and now the edges */
1334 for (i=0; i < get_class_n_supertypes(tp); i++)
1336 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1342 break; /* case k_type */
1345 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1347 } /* switch kind_or_entity */
1350 /*******************************************************************/
1351 /* dump analysis information that is expressed in graph terms. */
1352 /*******************************************************************/
1354 /* dump out edges */
1356 dump_out_edge (ir_node *n, void* env) {
1358 for (i = 0; i < get_irn_n_outs(n); i++) {
1359 assert(get_irn_out(n, i));
1360 fprintf (F, "edge: {sourcename: \"");
1362 fprintf (F, "\" targetname: \"");
1363 PRINT_NODEID(get_irn_out(n, i));
1364 fprintf (F, "\" color: red linestyle: dashed");
1370 dump_loop_label(ir_loop *loop) {
1371 fprintf (F, "loop %d, %d sons, %d nodes",
1372 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1375 static INLINE void dump_loop_info(ir_loop *loop) {
1376 fprintf (F, " info1: \"");
1377 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1378 #if DEBUG_libfirm /* GL @@@ debug analyses */
1379 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1385 dump_loop_node(ir_loop *loop) {
1386 fprintf (F, "node: {title: \"");
1388 fprintf (F, "\" label: \"");
1389 dump_loop_label(loop);
1391 dump_loop_info(loop);
1397 dump_loop_node_edge (ir_loop *loop, int i) {
1399 fprintf (F, "edge: {sourcename: \"");
1401 fprintf (F, "\" targetname: \"");
1402 PRINT_NODEID(get_loop_node(loop, i));
1403 fprintf (F, "\" color: green");
1408 dump_loop_son_edge (ir_loop *loop, int i) {
1410 fprintf (F, "edge: {sourcename: \"");
1412 fprintf (F, "\" targetname: \"");
1413 PRINT_LOOPID(get_loop_son(loop, i));
1414 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1415 get_loop_element_pos(loop, get_loop_son(loop, i)));
1419 void dump_loops (ir_loop *loop) {
1421 /* dump this loop node */
1422 dump_loop_node(loop);
1424 /* dump edges to nodes in loop -- only if it is a real loop */
1425 if (get_loop_depth(loop) != 0) {
1426 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1427 dump_loop_node_edge(loop, i);
1430 for (i = 0; i < get_loop_n_sons(loop); i++) {
1431 dump_loops(get_loop_son(loop, i));
1432 dump_loop_son_edge(loop, i);
1437 void dump_loop_nodes_into_graph(ir_graph *irg) {
1438 ir_graph *rem = current_ir_graph;
1439 current_ir_graph = irg;
1441 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1443 current_ir_graph = rem;
1447 /************************************************************************/
1448 /* open and close vcg file */
1449 /************************************************************************/
1452 dump_vcg_header(const char *name, const char *orientation) {
1461 if (!orientation) orientation = "bottom_to_top";
1465 "graph: { title: \"ir graph of %s\"\n"
1466 "display_edge_labels: %s\n"
1467 "layoutalgorithm: mindepth\n"
1468 "manhattan_edges: yes\n"
1469 "port_sharing: no\n"
1471 "classname 1: \"Data\"\n"
1472 "classname 2: \"Block\"\n"
1473 "classname 13:\"Control Flow\"\n"
1474 "classname 14:\"Memory\"\n"
1475 "classname 15:\"Dominators\"\n"
1476 "classname 3: \"Entity type\"\n"
1477 "classname 4: \"Entity owner\"\n"
1478 "classname 5: \"Method Param\"\n"
1479 "classname 6: \"Method Res\"\n"
1480 "classname 7: \"Super\"\n"
1481 "classname 8: \"Union\"\n"
1482 "classname 9: \"Points-to\"\n"
1483 "classname 10: \"Array Element Type\"\n"
1484 "classname 11: \"Overwrites\"\n"
1485 "classname 12: \"Member\"\n",
1486 name, label, orientation);
1488 fprintf (F, "\n"); /* a separator */
1491 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1492 const char *nm = get_irg_dump_name(irg);
1493 int len = strlen(nm);
1494 char *fname; /* filename to put the vcg information in */
1496 if (!suffix1) suffix1 = "";
1497 if (!suffix2) suffix2 = "";
1499 /** open file for vcg graph */
1500 fname = malloc (len + strlen(suffix1) + strlen(suffix2) + 5);
1501 strncpy (fname, nm, len); /* copy the filename */
1503 strcat (fname, suffix1); /* append file suffix */
1504 strcat (fname, suffix2); /* append file suffix */
1505 strcat (fname, ".vcg"); /* append the .vcg suffix */
1506 F = fopen (fname, "w"); /* open file for writing */
1508 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1513 static void vcg_open_name (const char *name, char *suffix) {
1514 char *fname; /* filename to put the vcg information in */
1516 if (!suffix) suffix = "";
1518 /** open file for vcg graph */
1519 fname = malloc (strlen(name) + 5 + strlen(suffix));
1520 strcpy (fname, name); /* copy the filename */
1521 strcat (fname, suffix);
1522 strcat (fname, ".vcg"); /* append the .vcg suffix */
1523 F = fopen (fname, "w"); /* open file for writing */
1525 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1530 static INLINE void dump_vcg_footer (void) {
1536 dump_vcg_footer(); /* print footer */
1537 fclose (F); /* close vcg file */
1540 /************************************************************************/
1541 /************************************************************************/
1542 /* Routines that dump all or parts of the firm representation to a file */
1543 /************************************************************************/
1544 /************************************************************************/
1546 /************************************************************************/
1547 /* Dump ir graphs, differnt formats and additional information. */
1548 /************************************************************************/
1550 /** Routine to dump a graph, blocks as conventional nodes.
1553 dump_ir_graph (ir_graph *irg)
1557 rem = current_ir_graph;
1559 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1561 current_ir_graph = irg;
1562 if (interprocedural_view) suffix = "-pure-ip";
1563 else suffix = "-pure";
1564 vcg_open (irg, dump_file_suffix, suffix);
1565 dump_vcg_header(get_irg_dump_name(irg), NULL);
1567 /* walk over the graph */
1568 /* dump_whole_node must be called in post visiting predecessors */
1569 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1571 /* dump the out edges in a separate walk */
1572 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1573 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1578 current_ir_graph = rem;
1583 dump_ir_block_graph (ir_graph *irg)
1588 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1590 if (interprocedural_view) suffix = "-ip";
1592 vcg_open (irg, dump_file_suffix, suffix);
1593 dump_vcg_header(get_irg_dump_name(irg), NULL);
1595 construct_block_lists(irg);
1597 for (i = 0; i < get_irp_n_irgs(); i++) {
1598 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1600 dump_graph(get_irp_irg(i));
1608 /** dumps a graph with type information
1611 dump_ir_graph_w_types (ir_graph *irg)
1613 ir_graph *rem = current_ir_graph;
1616 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1618 current_ir_graph = irg;
1620 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1621 else suffix = "-pure-wtypes";
1622 vcg_open (irg, dump_file_suffix, suffix);
1623 dump_vcg_header(get_irg_dump_name(irg), NULL);
1625 /* dump common ir graph */
1626 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1627 /* dump type info */
1628 type_walk_irg(irg, dump_type_info, NULL, NULL);
1629 inc_irg_visited(get_const_code_irg());
1630 /* dump edges from graph to type info */
1631 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1634 current_ir_graph = rem;
1638 dump_ir_block_graph_w_types (ir_graph *irg)
1642 ir_graph *rem = current_ir_graph;
1644 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1646 if (interprocedural_view) suffix = "-wtypes-ip";
1647 else suffix = "-wtypes";
1648 vcg_open (irg, dump_file_suffix, suffix);
1649 dump_vcg_header(get_irg_dump_name(irg), NULL);
1651 /* dump common blocked ir graph */
1652 construct_block_lists(irg);
1654 for (i = 0; i < get_irp_n_irgs(); i++) {
1655 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1657 dump_graph(get_irp_irg(i));
1662 /* dump type info */
1663 current_ir_graph = irg;
1664 type_walk_irg(irg, dump_type_info, NULL, NULL);
1665 inc_irg_visited(get_const_code_irg());
1667 /* dump edges from graph to type info */
1668 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1670 current_ir_graph = rem;
1674 /***********************************************************************/
1675 /* The following routines dump a control flow graph. */
1676 /***********************************************************************/
1679 dump_block_to_cfg (ir_node *block, void *env) {
1683 if (is_Block(block)) {
1684 /* This is a block. Dump a node for the block. */
1685 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1686 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1687 PRINT_NODEID(block);
1689 if (dump_dominator_information_flag)
1690 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1692 /* Dump the edges */
1693 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1694 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1695 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1696 fprintf (F, "edge: { sourcename: \"");
1697 PRINT_NODEID(block);
1698 fprintf (F, "\" targetname: \"");
1700 fprintf (F, "\"}\n");
1703 /* Dump dominator edge */
1704 if (dump_dominator_information_flag && get_Block_idom(block)) {
1705 pred = get_Block_idom(block);
1706 fprintf (F, "edge: { sourcename: \"");
1707 PRINT_NODEID(block);
1708 fprintf (F, "\" targetname: \"");
1710 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1716 dump_cfg (ir_graph *irg)
1718 ir_graph *rem = current_ir_graph;
1719 int ddif = dump_dominator_information_flag;
1720 int ipv = interprocedural_view;
1722 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1724 current_ir_graph = irg;
1726 vcg_open (irg, dump_file_suffix, "-cfg");
1727 dump_vcg_header(get_irg_dump_name(irg), NULL);
1729 if (interprocedural_view) {
1730 printf("Warning: dumping cfg not in interprocedural view!\n");
1731 interprocedural_view = 0;
1734 if (get_irg_dom_state(irg) != dom_consistent)
1735 dump_dominator_information_flag = 0;
1737 /* walk over the blocks in the graph */
1738 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1739 dump_node (get_irg_bad(irg));
1741 dump_dominator_information_flag = ddif;
1742 interprocedural_view = ipv;
1744 current_ir_graph = rem;
1749 /* Dump all irgs in interprocedural view to a single file. */
1750 void dump_all_cg_block_graph(void) {
1752 int rem_view = interprocedural_view;
1753 interprocedural_view = 1;
1755 vcg_open_name ("All_graphs", dump_file_suffix);
1756 dump_vcg_header("All_graphs", NULL);
1758 /* collect nodes in all irgs reachable in call graph*/
1759 for (i = 0; i < get_irp_n_irgs(); i++)
1760 ird_set_irg_link(get_irp_irg(i), NULL);
1762 cg_walk(clear_link, collect_node, NULL);
1764 /* dump all graphs */
1765 for (i = 0; i < get_irp_n_irgs(); i++) {
1766 current_ir_graph = get_irp_irg(i);
1767 assert(ird_get_irg_link(current_ir_graph));
1768 dump_graph(current_ir_graph);
1769 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1773 interprocedural_view = rem_view;
1776 /***********************************************************************/
1777 /* the following routines dumps type information without any ir nodes. */
1778 /***********************************************************************/
1781 dump_type_graph (ir_graph *irg)
1784 rem = current_ir_graph;
1786 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1788 current_ir_graph = irg;
1790 vcg_open (irg, dump_file_suffix, "-type");
1791 dump_vcg_header(get_irg_dump_name(irg), NULL);
1793 /* walk over the blocks in the graph */
1794 type_walk_irg(irg, dump_type_info, NULL, NULL);
1795 /* The walker for the const code can be called several times for the
1796 same (sub) experssion. So that no nodes are dumped several times
1797 we decrease the visited flag of the corresponding graph after each
1798 walk. So now increase it finally. */
1799 inc_irg_visited(get_const_code_irg());
1802 current_ir_graph = rem;
1806 dump_all_types (void)
1808 vcg_open_name ("All_types", dump_file_suffix);
1809 dump_vcg_header("All_types", NULL);
1810 type_walk(dump_type_info, NULL, NULL);
1811 inc_irg_visited(get_const_code_irg());
1816 dump_class_hierarchy (bool entities)
1818 vcg_open_name ("class_hierarchy", dump_file_suffix);
1819 dump_vcg_header("class_hierarchy", NULL);
1821 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1823 type_walk(dump_class_hierarchy_node, NULL, NULL);
1827 /***********************************************************************/
1828 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1830 /* dump_ir_block_graph */
1832 /* dump_type_graph */
1833 /* dump_ir_graph_w_types */
1834 /***********************************************************************/
1836 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1838 for (i=0; i < get_irp_n_irgs(); i++) {
1839 dmp_grph(get_irp_irg(i));
1844 /**********************************************************************************
1845 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1846 * packed together in one subgraph *
1847 **********************************************************************************/
1851 void dump_loops_standalone (ir_loop *loop) {
1852 int i, loop_node_started = 0, son_number = 0, first = 0;
1855 /* Dump a new loop node. */
1856 dump_loop_node(loop);
1858 /* Dump the loop elements. */
1859 for(i = 0; i < get_loop_n_elements(loop); i++)
1861 le = get_loop_element(loop, i);
1863 ir_loop *son = le.son;
1864 if (get_kind(son) == k_ir_loop)
1866 /* We are a loop son -> Recurse */
1868 if(loop_node_started) /* Close the "firm-nodes" node first if we started one. */
1870 fprintf(F, "\" }\n");
1871 fprintf (F, "edge: {sourcename: \"");
1873 fprintf (F, "\" targetname: \"");
1875 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1876 loop_node_started = 0;
1878 dump_loop_son_edge(loop, son_number++);
1879 dump_loops_standalone(son);
1883 /* We are a loop node -> Collect firm nodes */
1885 ir_node *n = le.node;
1887 if (!loop_node_started)
1889 /* Start a new node which contains all firm nodes of the current loop */
1890 fprintf (F, "node: { title: \"");
1892 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
1893 loop_node_started = 1;
1899 dump_node_opcode(n);
1901 dump_node_typeinfo(n);
1903 dump_node_nodeattr(n);
1904 fprintf (F, " %ld", get_irn_node_nr(n));
1909 if(loop_node_started)
1911 fprintf(F, "\" }\n");
1912 fprintf (F, "edge: {sourcename: \"");
1914 fprintf (F, "\" targetname: \"");
1916 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1917 loop_node_started = 0;
1921 void dump_loop_tree(ir_graph *irg, char *suffix)
1923 ir_graph *rem = current_ir_graph;
1924 int el_rem = edge_label;
1927 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1929 current_ir_graph = irg;
1931 vcg_open(irg, suffix, "-looptree");
1932 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
1934 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
1938 edge_label = el_rem;
1939 current_ir_graph = rem;
1943 /*******************************************************************************/
1944 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
1945 /*******************************************************************************/
1947 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
1948 int i, son_number = 0, node_number = 0;
1950 if (dump_loop_information_flag) dump_loop_node(loop);
1952 for (i = 0; i < get_loop_n_elements(loop); i++) {
1953 loop_element le = get_loop_element(loop, i);
1954 if (*(le.kind) == k_ir_loop) {
1955 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
1957 collect_nodeloop(le.son, loopnodes);
1959 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
1960 eset_insert(loopnodes, le.node);
1965 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
1968 for(i = 0; i < get_loop_n_elements(loop); i++) {
1969 loop_element le = get_loop_element(loop, i);
1970 if (*(le.kind) == k_ir_loop) {
1972 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
1974 if (is_Block(le.node)) start = 0; else start = -1;
1975 for (j = start; j < get_irn_arity(le.node); j++) {
1976 ir_node *pred = get_irn_n(le.node, j);
1977 if (!eset_contains(loopnodes, pred)) {
1978 eset_insert(extnodes, pred);
1979 if (!is_Block(pred)) {
1980 pred = get_nodes_block(pred);
1981 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
1989 void dump_loop (ir_loop *l, char *suffix) {
1991 eset *loopnodes = eset_create();
1992 eset *extnodes = eset_create();
1995 sprintf(name, "loop_%d", get_loop_loop_nr(l));
1996 vcg_open_name (name, suffix);
1997 dump_vcg_header(name, NULL);
1999 /* collect all nodes to dump */
2000 collect_nodeloop(l, loopnodes);
2001 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2003 /* build block lists */
2004 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2005 set_irn_link(n, NULL);
2006 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2007 set_irn_link(n, NULL);
2008 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2010 b = get_nodes_block(n);
2011 set_irn_link(n, get_irn_link(b));
2014 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2016 b = get_nodes_block(n);
2017 set_irn_link(n, get_irn_link(b));
2021 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2023 fprintf(F, "graph: { title: \"");
2025 fprintf(F, "\" label: \"");
2026 dump_node_opcode(b);
2027 fprintf (F, " %ld", get_irn_node_nr(b));
2028 fprintf(F, "\" status:clustered color:yellow\n");
2030 /* dump the blocks edges */
2031 dump_ir_data_edges(b);
2033 /* dump the nodes that go into the block */
2034 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2035 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2037 overrule_nodecolor = NULL;
2038 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2041 /* Close the vcg information for the block */
2043 dump_const_node_local(b);
2046 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2048 fprintf(F, "graph: { title: \"");
2050 fprintf(F, "\" label: \"");
2051 dump_node_opcode(b);
2052 fprintf (F, " %ld", get_irn_node_nr(b));
2053 fprintf(F, "\" status:clustered color:lightblue\n");
2055 /* dump the nodes that go into the block */
2056 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2057 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2059 overrule_nodecolor = NULL;
2060 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2063 /* Close the vcg information for the block */
2065 dump_const_node_local(b);
2069 eset_destroy(loopnodes);
2070 eset_destroy(extnodes);