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 "color: red"
61 #define MEM_EDGE_ATTR "color: blue"
62 #define DOMINATOR_EDGE_ATTR "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 3: \"Entity type\"\n"
1474 "classname 4: \"Entity owner\"\n"
1475 "classname 5: \"Method Param\"\n"
1476 "classname 6: \"Method Res\"\n"
1477 "classname 7: \"Super\"\n"
1478 "classname 8: \"Union\"\n"
1479 "classname 9: \"Points-to\"\n"
1480 "classname 10: \"Array Element Type\"\n"
1481 "classname 11: \"Overwrites\"\n"
1482 "classname 12: \"Member\"\n",
1483 name, label, orientation);
1485 fprintf (F, "\n"); /* a separator */
1488 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1489 const char *nm = get_irg_dump_name(irg);
1490 int len = strlen(nm);
1491 char *fname; /* filename to put the vcg information in */
1493 if (!suffix1) suffix1 = "";
1494 if (!suffix2) suffix2 = "";
1496 /** open file for vcg graph */
1497 fname = malloc (len + strlen(suffix1) + strlen(suffix2) + 5);
1498 strncpy (fname, nm, len); /* copy the filename */
1500 strcat (fname, suffix1); /* append file suffix */
1501 strcat (fname, suffix2); /* append file suffix */
1502 strcat (fname, ".vcg"); /* append the .vcg suffix */
1503 F = fopen (fname, "w"); /* open file for writing */
1505 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1510 static void vcg_open_name (const char *name, char *suffix) {
1511 char *fname; /* filename to put the vcg information in */
1513 if (!suffix) suffix = "";
1515 /** open file for vcg graph */
1516 fname = malloc (strlen(name) + 5 + strlen(suffix));
1517 strcpy (fname, name); /* copy the filename */
1518 strcat (fname, suffix);
1519 strcat (fname, ".vcg"); /* append the .vcg suffix */
1520 F = fopen (fname, "w"); /* open file for writing */
1522 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1527 static INLINE void dump_vcg_footer (void) {
1533 dump_vcg_footer(); /* print footer */
1534 fclose (F); /* close vcg file */
1537 /************************************************************************/
1538 /************************************************************************/
1539 /* Routines that dump all or parts of the firm representation to a file */
1540 /************************************************************************/
1541 /************************************************************************/
1543 /************************************************************************/
1544 /* Dump ir graphs, differnt formats and additional information. */
1545 /************************************************************************/
1547 /** Routine to dump a graph, blocks as conventional nodes.
1550 dump_ir_graph (ir_graph *irg)
1554 rem = current_ir_graph;
1556 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1558 current_ir_graph = irg;
1559 if (interprocedural_view) suffix = "-pure-ip";
1560 else suffix = "-pure";
1561 vcg_open (irg, dump_file_suffix, suffix);
1562 dump_vcg_header(get_irg_dump_name(irg), NULL);
1564 /* walk over the graph */
1565 /* dump_whole_node must be called in post visiting predecessors */
1566 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1568 /* dump the out edges in a separate walk */
1569 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1570 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1575 current_ir_graph = rem;
1580 dump_ir_block_graph (ir_graph *irg)
1585 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1587 if (interprocedural_view) suffix = "-ip";
1589 vcg_open (irg, dump_file_suffix, suffix);
1590 dump_vcg_header(get_irg_dump_name(irg), NULL);
1592 construct_block_lists(irg);
1594 for (i = 0; i < get_irp_n_irgs(); i++) {
1595 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1597 dump_graph(get_irp_irg(i));
1605 /** dumps a graph with type information
1608 dump_ir_graph_w_types (ir_graph *irg)
1610 ir_graph *rem = current_ir_graph;
1613 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1615 current_ir_graph = irg;
1617 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1618 else suffix = "-pure-wtypes";
1619 vcg_open (irg, dump_file_suffix, suffix);
1620 dump_vcg_header(get_irg_dump_name(irg), NULL);
1622 /* dump common ir graph */
1623 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1624 /* dump type info */
1625 type_walk_irg(irg, dump_type_info, NULL, NULL);
1626 inc_irg_visited(get_const_code_irg());
1627 /* dump edges from graph to type info */
1628 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1631 current_ir_graph = rem;
1635 dump_ir_block_graph_w_types (ir_graph *irg)
1639 ir_graph *rem = current_ir_graph;
1641 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1643 if (interprocedural_view) suffix = "-wtypes-ip";
1644 else suffix = "-wtypes";
1645 vcg_open (irg, dump_file_suffix, suffix);
1646 dump_vcg_header(get_irg_dump_name(irg), NULL);
1648 /* dump common blocked ir graph */
1649 construct_block_lists(irg);
1651 for (i = 0; i < get_irp_n_irgs(); i++) {
1652 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1654 dump_graph(get_irp_irg(i));
1659 /* dump type info */
1660 current_ir_graph = irg;
1661 type_walk_irg(irg, dump_type_info, NULL, NULL);
1662 inc_irg_visited(get_const_code_irg());
1664 /* dump edges from graph to type info */
1665 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1667 current_ir_graph = rem;
1671 /***********************************************************************/
1672 /* The following routines dump a control flow graph. */
1673 /***********************************************************************/
1676 dump_block_to_cfg (ir_node *block, void *env) {
1680 if (is_Block(block)) {
1681 /* This is a block. Dump a node for the block. */
1682 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1683 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1684 PRINT_NODEID(block);
1686 if (dump_dominator_information_flag)
1687 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1689 /* Dump the edges */
1690 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1691 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1692 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1693 fprintf (F, "edge: { sourcename: \"");
1694 PRINT_NODEID(block);
1695 fprintf (F, "\" targetname: \"");
1697 fprintf (F, "\"}\n");
1700 /* Dump dominator edge */
1701 if (dump_dominator_information_flag && get_Block_idom(block)) {
1702 pred = get_Block_idom(block);
1703 fprintf (F, "edge: { sourcename: \"");
1704 PRINT_NODEID(block);
1705 fprintf (F, "\" targetname: \"");
1707 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1713 dump_cfg (ir_graph *irg)
1715 ir_graph *rem = current_ir_graph;
1716 int ddif = dump_dominator_information_flag;
1717 int ipv = interprocedural_view;
1719 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1721 current_ir_graph = irg;
1723 vcg_open (irg, dump_file_suffix, "-cfg");
1724 dump_vcg_header(get_irg_dump_name(irg), NULL);
1726 if (interprocedural_view) {
1727 printf("Warning: dumping cfg not in interprocedural view!\n");
1728 interprocedural_view = 0;
1731 if (get_irg_dom_state(irg) != dom_consistent)
1732 dump_dominator_information_flag = 0;
1734 /* walk over the blocks in the graph */
1735 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1736 dump_node (get_irg_bad(irg));
1738 dump_dominator_information_flag = ddif;
1739 interprocedural_view = ipv;
1741 current_ir_graph = rem;
1746 /* Dump all irgs in interprocedural view to a single file. */
1747 void dump_all_cg_block_graph(void) {
1749 int rem_view = interprocedural_view;
1750 interprocedural_view = 1;
1752 vcg_open_name ("All_graphs", dump_file_suffix);
1753 dump_vcg_header("All_graphs", NULL);
1755 /* collect nodes in all irgs reachable in call graph*/
1756 for (i = 0; i < get_irp_n_irgs(); i++)
1757 ird_set_irg_link(get_irp_irg(i), NULL);
1759 cg_walk(clear_link, collect_node, NULL);
1761 /* dump all graphs */
1762 for (i = 0; i < get_irp_n_irgs(); i++) {
1763 current_ir_graph = get_irp_irg(i);
1764 assert(ird_get_irg_link(current_ir_graph));
1765 dump_graph(current_ir_graph);
1766 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1770 interprocedural_view = rem_view;
1773 /***********************************************************************/
1774 /* the following routines dumps type information without any ir nodes. */
1775 /***********************************************************************/
1778 dump_type_graph (ir_graph *irg)
1781 rem = current_ir_graph;
1783 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1785 current_ir_graph = irg;
1787 vcg_open (irg, dump_file_suffix, "-type");
1788 dump_vcg_header(get_irg_dump_name(irg), NULL);
1790 /* walk over the blocks in the graph */
1791 type_walk_irg(irg, dump_type_info, NULL, NULL);
1792 /* The walker for the const code can be called several times for the
1793 same (sub) experssion. So that no nodes are dumped several times
1794 we decrease the visited flag of the corresponding graph after each
1795 walk. So now increase it finally. */
1796 inc_irg_visited(get_const_code_irg());
1799 current_ir_graph = rem;
1803 dump_all_types (void)
1805 vcg_open_name ("All_types", dump_file_suffix);
1806 dump_vcg_header("All_types", NULL);
1807 type_walk(dump_type_info, NULL, NULL);
1808 inc_irg_visited(get_const_code_irg());
1813 dump_class_hierarchy (bool entities)
1815 vcg_open_name ("class_hierarchy", dump_file_suffix);
1816 dump_vcg_header("class_hierarchy", NULL);
1818 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1820 type_walk(dump_class_hierarchy_node, NULL, NULL);
1824 /***********************************************************************/
1825 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1827 /* dump_ir_block_graph */
1829 /* dump_type_graph */
1830 /* dump_ir_graph_w_types */
1831 /***********************************************************************/
1833 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1835 for (i=0; i < get_irp_n_irgs(); i++) {
1836 dmp_grph(get_irp_irg(i));
1841 /**********************************************************************************
1842 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1843 * packed together in one subgraph *
1844 **********************************************************************************/
1848 void dump_loops_standalone (ir_loop *loop) {
1849 int i, loop_node_started = 0, son_number = 0, first = 0;
1852 /* Dump a new loop node. */
1853 dump_loop_node(loop);
1855 /* Dump the loop elements. */
1856 for(i = 0; i < get_loop_n_elements(loop); i++)
1858 le = get_loop_element(loop, i);
1860 ir_loop *son = le.son;
1861 if (get_kind(son) == k_ir_loop)
1863 /* We are a loop son -> Recurse */
1865 if(loop_node_started) /* Close the "firm-nodes" node first if we started one. */
1867 fprintf(F, "\" }\n");
1868 fprintf (F, "edge: {sourcename: \"");
1870 fprintf (F, "\" targetname: \"");
1872 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1873 loop_node_started = 0;
1875 dump_loop_son_edge(loop, son_number++);
1876 dump_loops_standalone(son);
1880 /* We are a loop node -> Collect firm nodes */
1882 ir_node *n = le.node;
1884 if (!loop_node_started)
1886 /* Start a new node which contains all firm nodes of the current loop */
1887 fprintf (F, "node: { title: \"");
1889 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
1890 loop_node_started = 1;
1896 dump_node_opcode(n);
1898 dump_node_typeinfo(n);
1900 dump_node_nodeattr(n);
1901 fprintf (F, " %ld", get_irn_node_nr(n));
1906 if(loop_node_started)
1908 fprintf(F, "\" }\n");
1909 fprintf (F, "edge: {sourcename: \"");
1911 fprintf (F, "\" targetname: \"");
1913 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1914 loop_node_started = 0;
1918 void dump_loop_tree(ir_graph *irg, char *suffix)
1920 ir_graph *rem = current_ir_graph;
1921 int el_rem = edge_label;
1924 if(strncmp(get_irg_dump_name(irg),dump_file_filter,strlen(dump_file_filter))!=0) return;
1926 current_ir_graph = irg;
1928 vcg_open(irg, suffix, "-looptree");
1929 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
1931 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
1935 edge_label = el_rem;
1936 current_ir_graph = rem;
1940 /*******************************************************************************/
1941 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
1942 /*******************************************************************************/
1944 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
1945 int i, son_number = 0, node_number = 0;
1947 if (dump_loop_information_flag) dump_loop_node(loop);
1949 for (i = 0; i < get_loop_n_elements(loop); i++) {
1950 loop_element le = get_loop_element(loop, i);
1951 if (*(le.kind) == k_ir_loop) {
1952 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
1954 collect_nodeloop(le.son, loopnodes);
1956 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
1957 eset_insert(loopnodes, le.node);
1962 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
1965 for(i = 0; i < get_loop_n_elements(loop); i++) {
1966 loop_element le = get_loop_element(loop, i);
1967 if (*(le.kind) == k_ir_loop) {
1969 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
1971 if (is_Block(le.node)) start = 0; else start = -1;
1972 for (j = start; j < get_irn_arity(le.node); j++) {
1973 ir_node *pred = get_irn_n(le.node, j);
1974 if (!eset_contains(loopnodes, pred)) {
1975 eset_insert(extnodes, pred);
1976 if (!is_Block(pred)) {
1977 pred = get_nodes_block(pred);
1978 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
1986 void dump_loop (ir_loop *l, char *suffix) {
1988 eset *loopnodes = eset_create();
1989 eset *extnodes = eset_create();
1992 sprintf(name, "loop_%d", get_loop_loop_nr(l));
1993 vcg_open_name (name, suffix);
1994 dump_vcg_header(name, NULL);
1996 /* collect all nodes to dump */
1997 collect_nodeloop(l, loopnodes);
1998 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2000 /* build block lists */
2001 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2002 set_irn_link(n, NULL);
2003 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2004 set_irn_link(n, NULL);
2005 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2007 b = get_nodes_block(n);
2008 set_irn_link(n, get_irn_link(b));
2011 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2013 b = get_nodes_block(n);
2014 set_irn_link(n, get_irn_link(b));
2018 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2020 fprintf(F, "graph: { title: \"");
2022 fprintf(F, "\" label: \"");
2023 dump_node_opcode(b);
2024 fprintf (F, " %ld", get_irn_node_nr(b));
2025 fprintf(F, "\" status:clustered color:yellow\n");
2027 /* dump the blocks edges */
2028 dump_ir_data_edges(b);
2030 /* dump the nodes that go into the block */
2031 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2032 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2034 overrule_nodecolor = NULL;
2035 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2038 /* Close the vcg information for the block */
2040 dump_const_node_local(b);
2043 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2045 fprintf(F, "graph: { title: \"");
2047 fprintf(F, "\" label: \"");
2048 dump_node_opcode(b);
2049 fprintf (F, " %ld", get_irn_node_nr(b));
2050 fprintf(F, "\" status:clustered color:lightblue\n");
2052 /* dump the nodes that go into the block */
2053 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2054 if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2056 overrule_nodecolor = NULL;
2057 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2060 /* Close the vcg information for the block */
2062 dump_const_node_local(b);
2066 eset_destroy(loopnodes);
2067 eset_destroy(extnodes);