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 /* file to dump to */
201 static void dump_whole_node(ir_node *n, void* env);
202 static INLINE void dump_loop_nodes_into_graph(ir_graph *irg);
204 /*******************************************************************/
205 /* Helper functions. */
206 /*******************************************************************/
208 /* Use private link attr to be able to call dumper anywhere without
209 destroying link fields. */
211 static pmap *irdump_link_map = NULL;
213 static void init_irdump(void) {
214 /* We need a new, empty map. */
215 if (irdump_link_map) pmap_destroy(irdump_link_map);
216 irdump_link_map = pmap_create();
220 void *ird_get_irn_link(ir_node *n) {
222 if (!irdump_link_map) return NULL;
224 if (pmap_contains(irdump_link_map, (void *)n))
225 res = pmap_get(irdump_link_map, (void *)n);
229 void ird_set_irn_link(ir_node *n, void *x) {
230 if (!irdump_link_map) init_irdump();
231 pmap_insert(irdump_link_map, (void *)n, x);
234 void *ird_get_irg_link(ir_graph *irg) {
236 if (!irdump_link_map) return NULL;
238 if (pmap_contains(irdump_link_map, (void *)irg))
239 res = pmap_get(irdump_link_map, (void *)irg);
243 void ird_set_irg_link(ir_graph *irg, void *x) {
244 if (!irdump_link_map) init_irdump();
245 pmap_insert(irdump_link_map, (void *)irg, x);
248 static void clear_link(ir_node * node, void * env) {
249 ird_set_irn_link(node, NULL);
253 static int node_floats(ir_node *n) {
254 return ((get_op_pinned(get_irn_op(n)) == floats) &&
255 (get_irg_pinned(current_ir_graph) == floats));
258 static const char *get_ent_dump_name (entity *ent) {
259 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
260 if (ent->ld_name) return get_id_str(ent->ld_name);
261 return get_id_str(ent->name);
264 static const char *get_irg_dump_name (ir_graph *irg) {
265 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
266 entity *ent = get_irg_ent(irg);
267 return get_ent_dump_name(ent);
270 static void collect_node(ir_node * node, void *env) {
273 || get_irn_op(node) == op_Bad
274 || get_irn_op(node) == op_Unknown) {
275 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
276 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
277 ARR_APP1(ir_node *, arr, node);
278 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
280 ir_node * block = get_nodes_block(node);
281 ird_set_irn_link(node, ird_get_irn_link(block));
282 ird_set_irn_link(block, node);
286 /** Construct lists to walk ir block-wise.
288 * Collects all blocks, nodes not pinned,
289 * Bad and Unknown into a flexible array in link field of
290 * irg they belong to. Sets the irg link field to NULL in all
291 * graphs not visited.
292 * Free the list with DEL_ARR_F. */
293 static ir_node ** construct_block_lists(ir_graph *irg) {
295 ir_graph *rem = current_ir_graph;
296 current_ir_graph = irg;
298 for (i = 0; i < get_irp_n_irgs(); i++)
299 ird_set_irg_link(get_irp_irg(i), NULL);
301 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
303 current_ir_graph = rem;
304 return ird_get_irg_link(irg);
307 /*******************************************************************/
308 /* flags to steer output */
309 /*******************************************************************/
311 /* A compiler option to turn off edge labels */
313 /* A compiler option to turn off dumping values of constant entities */
314 int const_entities = 1;
315 /* A compiler option to dump the keep alive edges */
316 int dump_keepalive = 0;
317 /* Compiler options to dump analysis information in dump_ir_graph */
318 int dump_out_edge_flag = 0;
319 int dump_dominator_information_flag = 0;
320 int dump_loop_information_flag = 0;
321 int dump_backedge_information_flag = 1;
322 int dump_const_local = 0;
323 bool opt_dump_analysed_type_info = 1;
324 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
326 char* overrule_nodecolor = NULL;
328 INLINE bool get_opt_dump_const_local(void) {
329 if (!dump_out_edge_flag && !dump_loop_information_flag)
330 return dump_const_local;
335 /* To turn off display of edge labels. Edge labels offen cause xvcg to
336 abort with a segmentation fault. */
337 void turn_off_edge_labels(void) {
341 void dump_consts_local(bool b) {
342 dump_const_local = b;
345 void turn_off_constant_entity_values(void) {
349 void dump_keepalive_edges(bool b) {
353 bool get_opt_dump_keepalive_edges(void) {
354 return dump_keepalive;
357 void dump_out_edges(void) {
358 dump_out_edge_flag = 1;
361 void dump_dominator_information(void) {
362 dump_dominator_information_flag = 1;
365 void dump_loop_information(void) {
366 dump_loop_information_flag = 1;
369 void dont_dump_loop_information(void) {
370 dump_loop_information_flag = 0;
373 void dump_backedge_information(bool b) {
374 dump_backedge_information_flag = b;
377 /* Dump the information of type field specified in ana/irtypeinfo.h.
378 * If the flag is set, the type name is output in [] in the node label,
379 * else it is output as info.
381 void dump_analysed_type_info(bool b) {
382 opt_dump_analysed_type_info = b;
385 void dump_pointer_values_to_info(bool b) {
386 opt_dump_pointer_values_to_info = b;
389 /*******************************************************************/
390 /* Routines to dump information about a single ir node. */
391 /*******************************************************************/
394 dump_node_opcode (ir_node *n)
397 switch(get_irn_opcode(n)) {
402 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
403 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
408 if (get_SymConst_kind(n) == linkage_ptr_info) {
409 /* don't use get_SymConst_ptr_info as it mangles the name. */
410 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
412 assert(get_kind(get_SymConst_type(n)) == k_type);
413 assert(get_type_ident(get_SymConst_type(n)));
414 fprintf (F, "SymC %s ", get_type_name(get_SymConst_type(n)));
415 if (get_SymConst_kind(n) == type_tag)
423 if (!interprocedural_view) fprintf(F, "Proj'");
424 else fprintf(F, "%s", get_irn_opname(n));
428 if (interprocedural_view) {
429 fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_ent(get_irn_irg(n))));
435 fprintf (F, "%s", get_irn_opname(n));
442 dump_node_mode (ir_node *n)
444 switch (get_irn_opcode(n)) {
463 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
470 static void dump_node_typeinfo(ir_node *n) {
471 if (!opt_dump_analysed_type_info) return;
472 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
473 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
474 type *tp = get_irn_type(n);
476 fprintf (F, " [%s]", get_type_name(tp));
483 dump_node_nodeattr (ir_node *n)
485 switch (get_irn_opcode(n)) {
487 if (false && interprocedural_view) {
488 fprintf (F, "%s", get_ent_dump_name(get_irg_ent(current_ir_graph)));
492 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
493 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
495 fprintf (F, "%ld", get_Proj_proj(n));
499 fprintf (F, "%ld", get_Filter_proj(n));
502 fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
505 fprintf (F, "(%s)", get_type_name(get_Cast_type(n)));
508 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
517 dump_node_vcgattr (ir_node *n)
519 switch (get_irn_opcode(n)) {
526 fprintf (F, "color: blue");
529 fprintf (F, "color: lightyellow");
532 fprintf (F, "color: green");
538 fprintf (F, "color: yellow");
541 PRINT_DEFAULT_NODE_ATTR;
544 if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
548 dump_node_info (ir_node *n) {
552 fprintf (F, " info1: \"");
553 if (opt_dump_pointer_values_to_info)
554 fprintf (F, "addr: %p \n", (void *)n);
555 fprintf (F, "visited: %ld \n", get_irn_visited(n));
556 irg = get_irn_irg(n);
557 if (irg != get_const_code_irg())
558 fprintf (F, "irg: %s\n", get_ent_dump_name(get_irg_entity(irg)));
560 fprintf(F, "arity: %d", get_irn_arity(n));
561 if ((get_irn_op(n) == op_Block) ||
562 (get_irn_op(n) == op_Phi) ||
563 ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
564 fprintf(F, " backedges:");
566 for (i = 0; i < get_irn_arity(n); i++)
567 if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
573 switch (get_irn_opcode(n)) {
575 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
576 fprintf(F, "start of method of type %s \n", get_type_name(tp));
577 for (i = 0; i < get_method_n_params(tp); ++i)
578 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
581 fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
584 fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
587 fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
588 fprintf(F, " from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
591 type *tp = get_Call_type(n);
592 fprintf(F, "calling method of type %s \n", get_type_name(tp));
593 for (i = 0; i < get_method_n_params(tp); ++i)
594 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
595 for (i = 0; i < get_method_n_ress(tp); ++i)
596 fprintf(F, " resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
597 if (Call_has_callees(n)) {
598 fprintf(F, "possible callees: \n");
599 for (i = 0; i < get_Call_n_callees(n); i++) {
600 if (!get_Call_callee(n, i)) {
601 fprintf(F, " %d external method\n", i);
603 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
608 case iro_CallBegin: {
609 ir_node *call = get_CallBegin_call(n);
610 if (Call_has_callees(call)) {
611 fprintf(F, "possible callees: \n");
612 for (i = 0; i < get_Call_n_callees(call); i++) {
613 if (!get_Call_callee(call, i)) {
614 fprintf(F, " %d external method\n", i);
616 fprintf(F, " %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
622 if (!interprocedural_view) {
623 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
624 fprintf(F, "return in method of type %s \n", get_type_name(tp));
625 for (i = 0; i < get_method_n_ress(tp); ++i)
626 fprintf(F, " res %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
630 type *tp = get_Const_type(n);
631 assert(tp != none_type);
632 fprintf(F, "Const of type %s \n", get_type_name(get_Const_type(n)));
636 if (interprocedural_view) {
637 fprintf(F, "intra predecessor nodes:\n");
638 for (i = 0; i < get_irn_intra_arity(n); i++) {
639 ir_node *pred = get_irn_intra_n(n, i);
640 fprintf(F, " %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
643 fprintf(F, "inter predecessor nodes:\n");
644 for (i = 0; i < get_irn_inter_arity(n); i++) {
645 ir_node *pred = get_irn_inter_n(n, i);
646 fprintf(F, " %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
647 get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
655 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
656 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
657 if (get_irn_type(n) != none_type)
658 fprintf (F, "\nAnalysed type: %s", get_type_name(get_irn_type(n)));
665 bool is_constlike_node(ir_node *n) {
666 ir_op *op = get_irn_op(n);
667 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
671 /* outputs the predecessors of n, that are constants, local. I.e.,
672 generates a copy of the constant predecessors for each node called with. */
673 static void dump_const_node_local(ir_node *n) {
675 if (!get_opt_dump_const_local()) return;
677 /* Use visited flag to avoid outputting nodes twice.
678 initialize it first. */
679 for (i = 0; i < get_irn_arity(n); i++) {
680 ir_node *con = get_irn_n(n, i);
681 if (is_constlike_node(con)) {
682 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
686 for (i = 0; i < get_irn_arity(n); i++) {
687 ir_node *con = get_irn_n(n, i);
688 if (is_constlike_node(con) && irn_not_visited(con)) {
689 mark_irn_visited(con);
690 /* Generate a new name for the node by appending the names of
692 fprintf (F, "node: {title: "); PRINT_CONSTID(n, con);
693 fprintf(F, " label: \"");
694 dump_node_opcode(con);
695 dump_node_mode (con);
696 dump_node_typeinfo(con);
698 dump_node_nodeattr(con);
699 fprintf (F, " %ld", get_irn_node_nr(con));
701 dump_node_vcgattr(con);
709 dump_node (ir_node *n) {
710 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
712 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
716 dump_node_typeinfo(n);
718 dump_node_nodeattr(n);
719 fprintf (F, " %ld", get_irn_node_nr(n));
721 dump_node_vcgattr(n);
724 dump_const_node_local(n);
731 /* dump the edge to the block this node belongs to */
733 dump_ir_block_edge(ir_node *n) {
734 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
735 if (is_no_Block(n)) {
736 fprintf (F, "edge: { sourcename: \"");
738 fprintf (F, "\" targetname: \"");
739 PRINT_NODEID(get_nodes_block(n));
740 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
744 static void print_edge_vcgattr(ir_node *from, int to) {
747 if (dump_backedge_information_flag && is_backedge(from, to))
748 fprintf (F, BACK_EDGE_ATTR);
750 switch (get_irn_opcode(from)) {
752 fprintf (F, CF_EDGE_ATTR);
754 case iro_Start: break;
757 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
758 fprintf (F, CF_EDGE_ATTR);
759 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
760 fprintf (F, MEM_EDGE_ATTR);
763 case iro_EndReg: break;
764 case iro_EndExcept: break;
766 case iro_Break: break;
767 case iro_Cond: break;
770 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
772 case iro_Const: break;
773 case iro_SymConst:break;
776 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
778 case iro_CallBegin: break;
781 case iro_Minus: break;
787 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
795 case iro_Shrs: break;
798 case iro_Conv: break;
800 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
806 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
809 fprintf (F, MEM_EDGE_ATTR);
811 case iro_Tuple: break;
814 switch (get_irn_modecode(from)) {
816 fprintf (F, CF_EDGE_ATTR);
819 fprintf (F, MEM_EDGE_ATTR);
825 case iro_Unknown: break;
832 /* dump edges to our inputs */
834 dump_ir_data_edges(ir_node *n) {
835 int i, visited = get_irn_visited(n);
837 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
840 for (i = 0; i < get_irn_arity(n); i++) {
841 ir_node * pred = get_irn_n(n, i);
844 if ((interprocedural_view && get_irn_visited(pred) < visited))
845 continue; /* pred not dumped */
847 if (dump_backedge_information_flag && is_backedge(n, i))
848 fprintf (F, "backedge: {sourcename: \"");
850 fprintf (F, "edge: {sourcename: \"");
852 fprintf (F, "\" targetname: ");
853 if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
854 PRINT_CONSTID(n, pred);
856 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
858 fprintf (F, " label: \"%d\" ", i);
859 print_edge_vcgattr(n, i);
864 /** Dumps a node and its edges but not the block edge
867 dump_node_wo_blockedge (ir_node *n, void* env) {
869 dump_ir_data_edges(n);
872 /** Dumps a node and its edges.
875 dump_whole_node (ir_node *n, void* env) {
876 dump_node_wo_blockedge(n, env);
877 if (!node_floats(n)) dump_ir_block_edge(n);
881 dump_const_node(ir_node *n, void *env) {
882 if (is_Block(n)) return;
883 dump_node_wo_blockedge(n, env);
886 /***********************************************************************/
887 /* the following routines dump the nodes/irgs bracketed to graphs. */
888 /***********************************************************************/
890 /** Dumps a constant expression as entity initializer, array bound ...
892 static void dump_const_expression(ir_node *value) {
893 ir_graph *rem = current_ir_graph;
894 int rem_dump_const_local = dump_const_local;
895 dump_const_local = 0;
896 current_ir_graph = get_const_code_irg();
897 irg_walk(value, dump_const_node, NULL, NULL);
898 /* Decrease visited flag so that we walk with the same flag for the next
899 expresssion. This guarantees that we don't dump the same node twice,
900 as for const expressions cse is performed to save memory. */
901 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
902 current_ir_graph = rem;
903 dump_const_local = rem_dump_const_local;
906 /** Dump a block as graph containing its nodes.
908 * Expects to find nodes belonging to the block as list in its
910 * Dumps the edges of all nodes including itself. */
912 dump_whole_block(ir_node *block) {
914 assert(is_Block(block));
916 fprintf(F, "graph: { title: \"");
918 fprintf(F, "\" label: \"");
919 dump_node_opcode(block);
920 fprintf (F, " %ld", get_irn_node_nr(block));
922 if (get_opt_dump_abstvals())
923 fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
925 fprintf(F, "\" status:clustered color:%s \n",
926 get_Block_matured(block) ? "yellow" : "red");
928 /* dump the blocks edges */
929 dump_ir_data_edges(block);
931 /* dump the nodes that go into the block */
932 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
934 dump_ir_data_edges(node);
937 /* Close the vcg information for the block */
939 dump_const_node_local(block);
941 dump_chi_term(F, block);
946 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
947 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
949 dump_block_graph (ir_graph *irg) {
951 ir_graph *rem = current_ir_graph;
952 ir_node **arr = ird_get_irg_link(irg);
953 current_ir_graph = irg;
955 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
956 ir_node * node = arr[i];
957 if (is_Block(node)) {
958 /* Dumps the block and all the nodes in the block, which are to
959 be found in Block->link. */
960 dump_whole_block(node);
962 /* Nodes that are not in a Block. */
964 dump_ir_data_edges(node);
968 if (dump_loop_information_flag) dump_loop_nodes_into_graph(irg);
970 current_ir_graph = rem;
973 /** Dumps an irg as a graph.
974 * If interprocedural view edges can point to nodes out of this graph.
976 static void dump_graph(ir_graph *irg) {
978 fprintf(F, "graph: { title: \"");
980 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
981 get_ent_dump_name(get_irg_ent(irg)));
983 dump_block_graph (irg);
985 /* Close the vcg information for the irg */
989 /*******************************************************************/
990 /* Basic type and entity nodes and edges. */
991 /*******************************************************************/
993 /* dumps the edges between nodes and their type or entity attributes. */
994 static void dump_node2type_edges (ir_node *n, void *env)
998 switch (get_irn_opcode(n)) {
1000 /* @@@ some consts have an entity */
1003 if ( (get_SymConst_kind(n) == type_tag)
1004 || (get_SymConst_kind(n) == size))
1006 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1010 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1013 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1016 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1019 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1022 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1030 static void print_type_info(type *tp) {
1031 if (get_type_state(tp) == layout_undefined) {
1032 fprintf(F, "state: layout_undefined\n");
1034 fprintf(F, "state: layout_fixed,\n");
1036 if (get_type_mode(tp))
1037 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
1038 fprintf(F, "size: %dB,\n", get_type_size(tp));
1041 static void print_typespecific_info(type *tp) {
1042 switch (get_type_tpop_code(tp)) {
1045 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1059 case tpo_enumeration:
1073 static void print_typespecific_vcgattr(type *tp) {
1074 switch (get_type_tpop_code(tp)) {
1077 if (peculiarity_existent == get_class_peculiarity(tp))
1078 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1080 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1084 fprintf (F, " " TYPE_METH_NODE_ATTR);
1095 case tpo_enumeration:
1108 static void print_type_node(type *tp)
1110 fprintf (F, "node: {title: ");
1112 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name(tp));
1113 fprintf (F, " info1: \"");
1114 print_type_info(tp);
1115 print_typespecific_info(tp);
1117 print_typespecific_vcgattr(tp);
1121 #define X(a) case a: fprintf(F, #a); break
1122 void dump_entity_node(entity *ent)
1124 fprintf (F, "node: {title: \"");
1125 PRINT_ENTID(ent); fprintf(F, "\"");
1126 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1127 fprintf (F, "label: ");
1128 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1129 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1131 fprintf (F, "\nallocation: ");
1132 switch (get_entity_allocation(ent)) {
1133 X(allocation_dynamic);
1134 X(allocation_automatic);
1135 X(allocation_static);
1136 X(allocation_parameter);
1139 fprintf (F, "\nvisibility: ");
1140 switch (get_entity_visibility(ent)) {
1141 X(visibility_local);
1142 X(visibility_external_visible);
1143 X(visibility_external_allocated);
1146 fprintf (F, "\nvariability: ");
1147 switch (get_entity_variability(ent)) {
1148 X(variability_uninitialized);
1149 X(variability_initialized);
1150 X(variability_part_constant);
1151 X(variability_constant);
1154 fprintf (F, "\nvolatility: ");
1155 switch (get_entity_volatility(ent)) {
1156 X(volatility_non_volatile);
1157 X(volatility_is_volatile);
1160 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1161 fprintf(F, "\nname: %s\nld_name: %s",
1162 get_ent_dump_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1163 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1164 if (is_method_type(get_entity_type(ent))) {
1165 if (get_entity_irg(ent)) /* can be null */
1166 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1168 { fprintf (F, "\nirg = NULL"); }
1170 fprintf(F, "\"\n}\n");
1174 /* dumps a type or entity and it's edges. */
1176 dump_type_info (type_or_ent *tore, void *env) {
1177 int i = 0; /* to shutup gcc */
1179 /* dump this type or entity */
1181 switch (get_kind(tore)) {
1184 entity *ent = (entity *)tore;
1187 dump_entity_node(ent);
1189 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1190 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1191 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1192 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1193 if(is_class_type(get_entity_owner(ent))) {
1194 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1195 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1198 /* attached subgraphs */
1199 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1200 if (is_atomic_entity(ent)) {
1201 value = get_atomic_ent_value(ent);
1203 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1204 /* DDMN(value); $$$ */
1205 dump_const_expression(value);
1208 if (is_compound_entity(ent)) {
1209 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1210 value = get_compound_ent_value(ent, i);
1212 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1213 dump_const_expression(value);
1214 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1216 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1217 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1218 get_compound_ent_value_member(ent, i), i);
1227 type *tp = (type *)tore;
1228 print_type_node(tp);
1229 /* and now the edges */
1230 switch (get_type_tpop_code(tp)) {
1233 for (i=0; i < get_class_n_supertypes(tp); i++) {
1234 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1237 for (i=0; i < get_class_n_members(tp); i++) {
1238 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1243 for (i=0; i < get_struct_n_members(tp); i++) {
1244 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1249 for (i = 0; i < get_method_n_params(tp); i++)
1251 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1253 for (i = 0; i < get_method_n_ress(tp); i++)
1255 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1260 for (i = 0; i < get_union_n_members(tp); i++)
1262 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1267 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1268 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1269 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1270 ir_node *upper = get_array_upper_bound(tp, i);
1271 ir_node *lower = get_array_lower_bound(tp, i);
1272 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1273 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1274 dump_const_expression(upper);
1275 dump_const_expression(lower);
1279 case tpo_enumeration:
1284 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1292 break; /* case k_type */
1295 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1297 } /* switch kind_or_entity */
1300 /** For dumping class hierarchies.
1301 * Dumps a class type node and a superclass edge.
1302 * If env != null dumps entities of classes and overwrites edges.
1305 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1306 int i = 0; /* to shutup gcc */
1308 /* dump this type or entity */
1309 switch (get_kind(tore)) {
1311 entity *ent = (entity *)tore;
1312 if (get_entity_owner(ent) == get_glob_type()) break;
1313 if ((env) && is_class_type(get_entity_owner(ent))) {
1315 dump_entity_node(ent);
1317 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1318 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1320 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1323 } break; /* case k_entity */
1326 type *tp = (type *)tore;
1327 if (tp == get_glob_type()) break;
1328 switch (get_type_tpop_code(tp)) {
1330 print_type_node(tp);
1331 /* and now the edges */
1332 for (i=0; i < get_class_n_supertypes(tp); i++)
1334 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1340 break; /* case k_type */
1343 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1345 } /* switch kind_or_entity */
1348 /*******************************************************************/
1349 /* dump analysis information that is expressed in graph terms. */
1350 /*******************************************************************/
1352 /* dump out edges */
1354 dump_out_edge (ir_node *n, void* env) {
1356 for (i = 0; i < get_irn_n_outs(n); i++) {
1357 assert(get_irn_out(n, i));
1358 fprintf (F, "edge: {sourcename: \"");
1360 fprintf (F, "\" targetname: \"");
1361 PRINT_NODEID(get_irn_out(n, i));
1362 fprintf (F, "\" color: red linestyle: dashed");
1368 dump_loop_label(ir_loop *loop) {
1369 fprintf (F, "loop %d, %d sons, %d nodes",
1370 get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1373 static INLINE void dump_loop_info(ir_loop *loop) {
1374 fprintf (F, " info1: \"");
1375 fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1376 #if DEBUG_libfirm /* GL @@@ debug analyses */
1377 fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1383 dump_loop_node(ir_loop *loop) {
1384 fprintf (F, "node: {title: \"");
1386 fprintf (F, "\" label: \"");
1387 dump_loop_label(loop);
1389 dump_loop_info(loop);
1395 dump_loop_node_edge (ir_loop *loop, int i) {
1397 fprintf (F, "edge: {sourcename: \"");
1399 fprintf (F, "\" targetname: \"");
1400 PRINT_NODEID(get_loop_node(loop, i));
1401 fprintf (F, "\" color: green");
1406 dump_loop_son_edge (ir_loop *loop, int i) {
1408 fprintf (F, "edge: {sourcename: \"");
1410 fprintf (F, "\" targetname: \"");
1411 PRINT_LOOPID(get_loop_son(loop, i));
1412 fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1413 get_loop_element_pos(loop, get_loop_son(loop, i)));
1417 void dump_loops (ir_loop *loop) {
1419 /* dump this loop node */
1420 dump_loop_node(loop);
1422 /* dump edges to nodes in loop -- only if it is a real loop */
1423 if (get_loop_depth(loop) != 0) {
1424 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1425 dump_loop_node_edge(loop, i);
1428 for (i = 0; i < get_loop_n_sons(loop); i++) {
1429 dump_loops(get_loop_son(loop, i));
1430 dump_loop_son_edge(loop, i);
1435 void dump_loop_nodes_into_graph(ir_graph *irg) {
1436 ir_graph *rem = current_ir_graph;
1437 current_ir_graph = irg;
1439 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1441 current_ir_graph = rem;
1445 /************************************************************************/
1446 /* open and close vcg file */
1447 /************************************************************************/
1450 dump_vcg_header(const char *name, const char *orientation) {
1459 if (!orientation) orientation = "bottom_to_top";
1463 "graph: { title: \"ir graph of %s\"\n"
1464 "display_edge_labels: %s\n"
1465 "layoutalgorithm: mindepth\n"
1466 "manhattan_edges: yes\n"
1467 "port_sharing: no\n"
1469 "classname 1: \"Data\"\n"
1470 "classname 2: \"Block\"\n"
1471 "classname 3: \"Entity type\"\n"
1472 "classname 4: \"Entity owner\"\n"
1473 "classname 5: \"Method Param\"\n"
1474 "classname 6: \"Method Res\"\n"
1475 "classname 7: \"Super\"\n"
1476 "classname 8: \"Union\"\n"
1477 "classname 9: \"Points-to\"\n"
1478 "classname 10: \"Array Element Type\"\n"
1479 "classname 11: \"Overwrites\"\n"
1480 "classname 12: \"Member\"\n",
1481 name, label, orientation);
1483 fprintf (F, "\n"); /* a separator */
1486 static void vcg_open (ir_graph *irg, char * suffix1, char *suffix2) {
1487 const char *nm = get_irg_dump_name(irg);
1488 int len = strlen(nm);
1489 char *fname; /* filename to put the vcg information in */
1491 if (!suffix1) suffix1 = "";
1492 if (!suffix2) suffix2 = "";
1494 /** open file for vcg graph */
1495 fname = malloc (len + strlen(suffix1) + strlen(suffix2) + 5);
1496 strncpy (fname, nm, len); /* copy the filename */
1498 strcat (fname, suffix1); /* append file suffix */
1499 strcat (fname, suffix2); /* append file suffix */
1500 strcat (fname, ".vcg"); /* append the .vcg suffix */
1501 F = fopen (fname, "w"); /* open file for writing */
1503 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1508 static void vcg_open_name (const char *name, char *suffix) {
1509 char *fname; /* filename to put the vcg information in */
1511 if (!suffix) suffix = "";
1513 /** open file for vcg graph */
1514 fname = malloc (strlen(name) + 5 + strlen(suffix));
1515 strcpy (fname, name); /* copy the filename */
1516 strcat (fname, suffix);
1517 strcat (fname, ".vcg"); /* append the .vcg suffix */
1518 F = fopen (fname, "w"); /* open file for writing */
1520 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1525 static INLINE void dump_vcg_footer (void) {
1531 dump_vcg_footer(); /* print footer */
1532 fclose (F); /* close vcg file */
1535 /************************************************************************/
1536 /************************************************************************/
1537 /* Routines that dump all or parts of the firm representation to a file */
1538 /************************************************************************/
1539 /************************************************************************/
1541 /************************************************************************/
1542 /* Dump ir graphs, differnt formats and additional information. */
1543 /************************************************************************/
1545 /** Routine to dump a graph, blocks as conventional nodes.
1548 dump_ir_graph (ir_graph *irg)
1552 rem = current_ir_graph;
1553 current_ir_graph = irg;
1555 if (interprocedural_view) suffix = "-pure-ip";
1556 else suffix = "-pure";
1557 vcg_open (irg, dump_file_suffix, suffix);
1558 dump_vcg_header(get_irg_dump_name(irg), NULL);
1560 /* walk over the graph */
1561 /* dump_whole_node must be called in post visiting predecessors */
1562 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1564 /* dump the out edges in a separate walk */
1565 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1566 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1571 current_ir_graph = rem;
1576 dump_ir_block_graph (ir_graph *irg)
1581 if (interprocedural_view) suffix = "-ip";
1583 vcg_open (irg, dump_file_suffix, suffix);
1584 dump_vcg_header(get_irg_dump_name(irg), NULL);
1586 construct_block_lists(irg);
1588 for (i = 0; i < get_irp_n_irgs(); i++) {
1589 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1591 dump_graph(get_irp_irg(i));
1599 /** dumps a graph with type information
1602 dump_ir_graph_w_types (ir_graph *irg)
1604 ir_graph *rem = current_ir_graph;
1606 current_ir_graph = irg;
1608 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1609 else suffix = "-pure-wtypes";
1610 vcg_open (irg, dump_file_suffix, suffix);
1611 dump_vcg_header(get_irg_dump_name(irg), NULL);
1613 /* dump common ir graph */
1614 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1615 /* dump type info */
1616 type_walk_irg(irg, dump_type_info, NULL, NULL);
1617 inc_irg_visited(get_const_code_irg());
1618 /* dump edges from graph to type info */
1619 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1622 current_ir_graph = rem;
1626 dump_ir_block_graph_w_types (ir_graph *irg)
1630 ir_graph *rem = current_ir_graph;
1632 if (interprocedural_view) suffix = "-wtypes-ip";
1633 else suffix = "-wtypes";
1634 vcg_open (irg, dump_file_suffix, suffix);
1635 dump_vcg_header(get_irg_dump_name(irg), NULL);
1637 /* dump common blocked ir graph */
1638 construct_block_lists(irg);
1640 for (i = 0; i < get_irp_n_irgs(); i++) {
1641 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1643 dump_graph(get_irp_irg(i));
1648 /* dump type info */
1649 current_ir_graph = irg;
1650 type_walk_irg(irg, dump_type_info, NULL, NULL);
1651 inc_irg_visited(get_const_code_irg());
1653 /* dump edges from graph to type info */
1654 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1656 current_ir_graph = rem;
1660 /***********************************************************************/
1661 /* The following routines dump a control flow graph. */
1662 /***********************************************************************/
1665 dump_block_to_cfg (ir_node *block, void *env) {
1669 if (is_Block(block)) {
1670 /* This is a block. Dump a node for the block. */
1671 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1672 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1673 PRINT_NODEID(block);
1675 if (dump_dominator_information_flag)
1676 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1678 /* Dump the edges */
1679 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1680 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1681 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1682 fprintf (F, "edge: { sourcename: \"");
1683 PRINT_NODEID(block);
1684 fprintf (F, "\" targetname: \"");
1686 fprintf (F, "\"}\n");
1689 /* Dump dominator edge */
1690 if (dump_dominator_information_flag && get_Block_idom(block)) {
1691 pred = get_Block_idom(block);
1692 fprintf (F, "edge: { sourcename: \"");
1693 PRINT_NODEID(block);
1694 fprintf (F, "\" targetname: \"");
1696 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1702 dump_cfg (ir_graph *irg)
1704 ir_graph *rem = current_ir_graph;
1705 int ddif = dump_dominator_information_flag;
1706 int ipv = interprocedural_view;
1707 current_ir_graph = irg;
1709 vcg_open (irg, dump_file_suffix, "-cfg");
1710 dump_vcg_header(get_irg_dump_name(irg), NULL);
1712 if (interprocedural_view) {
1713 printf("Warning: dumping cfg not in interprocedural view!\n");
1714 interprocedural_view = 0;
1717 if (get_irg_dom_state(irg) != dom_consistent)
1718 dump_dominator_information_flag = 0;
1720 /* walk over the blocks in the graph */
1721 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1722 dump_node (get_irg_bad(irg));
1724 dump_dominator_information_flag = ddif;
1725 interprocedural_view = ipv;
1727 current_ir_graph = rem;
1732 /* Dump all irgs in interprocedural view to a single file. */
1733 void dump_all_cg_block_graph(void) {
1735 int rem_view = interprocedural_view;
1736 interprocedural_view = 1;
1738 vcg_open_name ("All_graphs", dump_file_suffix);
1739 dump_vcg_header("All_graphs", NULL);
1741 /* collect nodes in all irgs reachable in call graph*/
1742 for (i = 0; i < get_irp_n_irgs(); i++)
1743 ird_set_irg_link(get_irp_irg(i), NULL);
1745 cg_walk(clear_link, collect_node, NULL);
1747 /* dump all graphs */
1748 for (i = 0; i < get_irp_n_irgs(); i++) {
1749 current_ir_graph = get_irp_irg(i);
1750 assert(ird_get_irg_link(current_ir_graph));
1751 dump_graph(current_ir_graph);
1752 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1756 interprocedural_view = rem_view;
1759 /***********************************************************************/
1760 /* the following routines dumps type information without any ir nodes. */
1761 /***********************************************************************/
1764 dump_type_graph (ir_graph *irg)
1767 rem = current_ir_graph;
1768 current_ir_graph = irg;
1770 vcg_open (irg, dump_file_suffix, "-type");
1771 dump_vcg_header(get_irg_dump_name(irg), NULL);
1773 /* walk over the blocks in the graph */
1774 type_walk_irg(irg, dump_type_info, NULL, NULL);
1775 /* The walker for the const code can be called several times for the
1776 same (sub) experssion. So that no nodes are dumped several times
1777 we decrease the visited flag of the corresponding graph after each
1778 walk. So now increase it finally. */
1779 inc_irg_visited(get_const_code_irg());
1782 current_ir_graph = rem;
1786 dump_all_types (void)
1788 vcg_open_name ("All_types", dump_file_suffix);
1789 dump_vcg_header("All_types", NULL);
1790 type_walk(dump_type_info, NULL, NULL);
1791 inc_irg_visited(get_const_code_irg());
1796 dump_class_hierarchy (bool entities)
1798 vcg_open_name ("class_hierarchy", dump_file_suffix);
1799 dump_vcg_header("class_hierarchy", NULL);
1801 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1803 type_walk(dump_class_hierarchy_node, NULL, NULL);
1807 /***********************************************************************/
1808 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1810 /* dump_ir_block_graph */
1812 /* dump_type_graph */
1813 /* dump_ir_graph_w_types */
1814 /***********************************************************************/
1816 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1818 for (i=0; i < get_irp_n_irgs(); i++) {
1819 dmp_grph(get_irp_irg(i));
1824 /**********************************************************************************
1825 * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes *
1826 * packed together in one subgraph *
1827 **********************************************************************************/
1831 void dump_loops_standalone (ir_loop *loop) {
1832 int i, loop_node_started = 0, son_number = 0, first;
1835 /* Dump a new loop node. */
1836 dump_loop_node(loop);
1838 /* Dump the loop elements. */
1839 for(i = 0; i < get_loop_n_elements(loop); i++)
1841 le = get_loop_element(loop, i);
1843 ir_loop *son = le.son;
1844 if (get_kind(son) == k_ir_loop)
1846 /* We are a loop son -> Recurse */
1848 if(loop_node_started) /* Close the "firm-nodes" node first if we started one. */
1850 fprintf(F, "\" }\n");
1851 fprintf (F, "edge: {sourcename: \"");
1853 fprintf (F, "\" targetname: \"");
1855 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1856 loop_node_started = 0;
1858 dump_loop_son_edge(loop, son_number++);
1859 dump_loops_standalone(son);
1863 /* We are a loop node -> Collect firm nodes */
1865 ir_node *n = le.node;
1867 if (!loop_node_started)
1869 /* Start a new node which contains all firm nodes of the current loop */
1870 fprintf (F, "node: { title: \"");
1872 fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
1873 loop_node_started = 1;
1879 dump_node_opcode(n);
1881 dump_node_typeinfo(n);
1883 dump_node_nodeattr(n);
1884 fprintf (F, " %ld", get_irn_node_nr(n));
1889 if(loop_node_started)
1891 fprintf(F, "\" }\n");
1892 fprintf (F, "edge: {sourcename: \"");
1894 fprintf (F, "\" targetname: \"");
1896 fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
1897 loop_node_started = 0;
1901 void dump_loop_tree(ir_graph *irg, char *suffix)
1903 ir_graph *rem = current_ir_graph;
1904 int el_rem = edge_label;
1907 current_ir_graph = irg;
1909 vcg_open(irg, suffix, "-looptree");
1910 dump_vcg_header(get_irg_dump_name(irg), "top_to_bottom");
1912 if (get_irg_loop(irg)) dump_loops_standalone(get_irg_loop(irg));
1916 edge_label = el_rem;
1917 current_ir_graph = rem;
1921 /*******************************************************************************/
1922 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
1923 /*******************************************************************************/
1925 void collect_nodeloop(ir_loop *loop, eset *loopnodes) {
1926 int i, son_number = 0, node_number = 0;
1928 if (dump_loop_information_flag) dump_loop_node(loop);
1930 for (i = 0; i < get_loop_n_elements(loop); i++) {
1931 loop_element le = get_loop_element(loop, i);
1932 if (*(le.kind) == k_ir_loop) {
1933 if (dump_loop_information_flag) dump_loop_son_edge(loop, son_number++);
1935 collect_nodeloop(le.son, loopnodes);
1937 if (dump_loop_information_flag) dump_loop_node_edge(loop, node_number++);
1938 eset_insert(loopnodes, le.node);
1943 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
1946 for(i = 0; i < get_loop_n_elements(loop); i++) {
1947 loop_element le = get_loop_element(loop, i);
1948 if (*(le.kind) == k_ir_loop) {
1950 collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
1952 if (is_Block(le.node)) start = 0; else start = -1;
1953 for (j = start; j < get_irn_arity(le.node); j++) {
1954 ir_node *pred = get_irn_n(le.node, j);
1955 if (!eset_contains(loopnodes, pred)) {
1956 eset_insert(extnodes, pred);
1957 if (!is_Block(pred)) {
1958 pred = get_nodes_block(pred);
1959 if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
1967 void dump_loop (ir_loop *l, char *suffix) {
1969 eset *loopnodes = eset_create();
1970 eset *extnodes = eset_create();
1973 sprintf(name, "loop_%d", get_loop_loop_nr(l));
1974 vcg_open_name (name, suffix);
1975 dump_vcg_header(name, NULL);
1977 /* collect all nodes to dump */
1978 collect_nodeloop(l, loopnodes);
1979 collect_nodeloop_external_nodes(l, loopnodes, extnodes);
1981 /* build block lists */
1982 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
1983 set_irn_link(n, NULL);
1984 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
1985 set_irn_link(n, NULL);
1986 for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
1988 b = get_nodes_block(n);
1989 set_irn_link(n, get_irn_link(b));
1992 for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
1994 b = get_nodes_block(n);
1995 set_irn_link(n, get_irn_link(b));
1999 for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2001 fprintf(F, "graph: { title: \"");
2003 fprintf(F, "\" label: \"");
2004 dump_node_opcode(b);
2005 fprintf (F, " %ld", get_irn_node_nr(b));
2006 fprintf(F, "\" status:clustered color:yellow\n");
2008 /* dump the blocks edges */
2009 dump_ir_data_edges(b);
2011 /* dump the nodes that go into the block */
2012 for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2013 if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2015 overrule_nodecolor = NULL;
2016 if (!eset_contains(extnodes, n)) dump_ir_data_edges(n);
2019 /* Close the vcg information for the block */
2021 dump_const_node_local(b);
2024 for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2026 fprintf(F, "graph: { title: \"");
2028 fprintf(F, "\" label: \"");
2029 dump_node_opcode(b);
2030 fprintf (F, " %ld", get_irn_node_nr(b));
2031 fprintf(F, "\" status:clustered color:lightblue\n");
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(loopnodes, n)) overrule_nodecolor = "lightblue";
2037 overrule_nodecolor = NULL;
2038 if (eset_contains(loopnodes, n)) dump_ir_data_edges(n);
2041 /* Close the vcg information for the block */
2043 dump_const_node_local(b);
2047 eset_destroy(loopnodes);
2048 eset_destroy(extnodes);