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.
21 # include "irnode_t.h"
22 # include "irgraph_t.h"
23 # include "entity_t.h"
25 # include "firm_common_t.h"
30 # include "typewalk.h"
33 # include "type_or_entity.h"
45 /* Attributes of nodes */
46 #define PRINT_DEFAULT_NODE_ATTR
47 #define DEFAULT_NODE_ATTR " "
48 #define DEFAULT_TYPE_ATTRIBUTE " "
50 /* Attributes of edges between Firm nodes */
51 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
52 #define CF_EDGE_ATTR "color: red"
53 #define MEM_EDGE_ATTR "color: blue"
54 #define DOMINATOR_EDGE_ATTR "color: red"
56 #define BACK_EDGE_ATTR "linestyle: dashed "
58 /* Attributes of edges between Firm nodes and type/entity nodes */
59 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
61 /* Attributes of edges in type/entity graphs. */
62 #define TYPE_METH_NODE_ATTR "color: lightyellow"
63 #define TYPE_CLASS_NODE_ATTR "color: green"
64 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
65 #define ENTITY_NODE_ATTR "color: yellow"
66 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
67 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
68 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
69 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
70 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
71 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
72 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
73 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
74 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
75 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
76 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
77 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
78 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
81 #if DEBUG_libfirm && NODEID_AS_LABEL
82 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
83 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
84 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
85 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
86 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
89 #define PRINT_NODEID(X) fprintf(F, "n%p", (void*) X)
90 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *) X)
91 #define PRINT_ENTID(X) fprintf(F, "e%p", (void*) X)
92 #define PRINT_IRGID(X) fprintf(F, "g%p",(void*) X)
93 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*) X, (void*) Y)
96 #define PRINT_TYPE_TYPE_EDGE(S,T,...){fprintf (F, "edge: { sourcename: "); PRINT_TYPEID(S); fprintf (F, " targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
97 #define PRINT_TYPE_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: "); PRINT_TYPEID(S); fprintf (F, " targetname: \""); PRINT_ENTID(T); fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
98 #define PRINT_ENT_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S); fprintf (F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
99 #define PRINT_ENT_TYPE_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S); fprintf (F, "\" targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
100 #define PRINT_NODE_TYPE_EDGE(S,T,...){fprintf (F, "edge: { sourcename: \""); PRINT_NODEID(S); fprintf (F, "\" targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
101 #define PRINT_NODE_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_NODEID(S); fprintf (F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
102 #define PRINT_ENT_NODE_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S); fprintf (F, "\" targetname: \""); PRINT_NODEID(T); fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
104 /*******************************************************************/
105 /* global and ahead declarations */
106 /*******************************************************************/
108 /* A suffix to manipulate the file name. */
109 char *dump_file_suffix = NULL;
111 /* file to dump to */
114 static void dump_whole_node(ir_node *n, void* env);
115 static INLINE void dump_loop_info(ir_graph *irg);
117 /*******************************************************************/
118 /* Helper functions. */
119 /*******************************************************************/
121 /* Use private link attr to be able to call dumper anywhere without
122 destroying link fields. */
124 static pmap *irdump_link_map = NULL;
126 static void init_irdump(void) {
127 /* We need a new, empty map. */
128 if (irdump_link_map) pmap_destroy(irdump_link_map);
129 irdump_link_map = pmap_create();
133 void *ird_get_irn_link(ir_node *n) {
135 if (!irdump_link_map) return NULL;
137 if (pmap_contains(irdump_link_map, (void *)n))
138 res = pmap_get(irdump_link_map, (void *)n);
142 void ird_set_irn_link(ir_node *n, void *x) {
143 if (!irdump_link_map) init_irdump();
144 pmap_insert(irdump_link_map, (void *)n, x);
147 void *ird_get_irg_link(ir_graph *irg) {
149 if (!irdump_link_map) return NULL;
151 if (pmap_contains(irdump_link_map, (void *)irg))
152 res = pmap_get(irdump_link_map, (void *)irg);
156 void ird_set_irg_link(ir_graph *irg, void *x) {
157 if (!irdump_link_map) init_irdump();
158 pmap_insert(irdump_link_map, (void *)irg, x);
161 static void clear_link(ir_node * node, void * env) {
162 ird_set_irn_link(node, NULL);
166 static int node_floats(ir_node *n) {
167 return ((get_op_pinned(get_irn_op(n)) == floats) &&
168 (get_irg_pinned(current_ir_graph) == floats));
171 static ident *get_irg_dump_name (ir_graph *irg) {
172 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
173 entity *ent = get_irg_ent(irg);
174 if (ent->ld_name) return ent->ld_name;
178 static void collect_node(ir_node * node, void *env) {
181 || get_irn_op(node) == op_Bad
182 || get_irn_op(node) == op_Unknown) {
183 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
184 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
185 ARR_APP1(ir_node *, arr, node);
186 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
188 ir_node * block = get_nodes_block(node);
189 ird_set_irn_link(node, ird_get_irn_link(block));
190 ird_set_irn_link(block, node);
194 /** Construct lists to walk ir block-wise.
196 * Collects all blocks, nodes not pinned,
197 * Bad and Unknown into a flexible array in link field of
198 * irg they belong to. Sets the irg link field to NULL in all
199 * graphs not visited.
200 * Free the list with DEL_ARR_F. */
201 static ir_node ** construct_block_lists(ir_graph *irg) {
203 ir_graph *rem = current_ir_graph;
204 current_ir_graph = irg;
206 for (i = 0; i < get_irp_n_irgs(); i++)
207 ird_set_irg_link(get_irp_irg(i), NULL);
209 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
211 current_ir_graph = rem;
212 return ird_get_irg_link(irg);
215 /*******************************************************************/
216 /* flags to steer output */
217 /*******************************************************************/
219 /* A compiler option to turn off edge labels */
221 /* A compiler option to turn off dumping values of constant entities */
222 int const_entities = 1;
223 /* A compiler option to dump the keep alive edges */
224 int dump_keepalive = 0;
225 /* Compiler options to dump analysis information in dump_ir_graph */
226 int dump_out_edge_flag = 0;
227 int dump_dominator_information_flag = 0;
228 int dump_loop_information_flag = 0;
229 int dump_backedge_information_flag = 1;
230 int dump_const_local = 0;
231 bool opt_dump_analysed_type_info = 1;
232 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
234 INLINE bool get_opt_dump_const_local(void) {
235 if (!dump_out_edge_flag && !dump_loop_information_flag)
236 return dump_const_local;
241 /* To turn off display of edge labels. Edge labels offen cause xvcg to
242 abort with a segmentation fault. */
243 void turn_off_edge_labels(void) {
247 void dump_consts_local(bool b) {
248 dump_const_local = b;
251 void turn_off_constant_entity_values(void) {
255 void dump_keepalive_edges(bool b) {
259 bool get_opt_dump_keepalive_edges(void) {
260 return dump_keepalive;
263 void dump_out_edges(void) {
264 dump_out_edge_flag = 1;
267 void dump_dominator_information(void) {
268 dump_dominator_information_flag = 1;
271 void dump_loop_information(void) {
272 dump_loop_information_flag = 1;
275 void dont_dump_loop_information(void) {
276 dump_loop_information_flag = 0;
279 void dump_backedge_information(bool b) {
280 dump_backedge_information_flag = b;
283 /* Dump the information of type field specified in ana/irtypeinfo.h.
284 * If the flag is set, the type name is output in [] in the node label,
285 * else it is output as info.
287 void dump_analysed_type_info(bool b) {
288 opt_dump_analysed_type_info = b;
291 void dump_pointer_values_to_info(bool b) {
292 opt_dump_pointer_values_to_info = b;
295 /*******************************************************************/
296 /* Routines to dump information about a single ir node. */
297 /*******************************************************************/
300 dump_node_opcode (ir_node *n)
303 switch(get_irn_opcode(n)) {
308 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
309 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
314 if (get_SymConst_kind(n) == linkage_ptr_info) {
315 /* don't use get_SymConst_ptr_info as it mangles the name. */
316 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
318 assert(get_kind(get_SymConst_type(n)) == k_type);
319 assert(get_type_ident(get_SymConst_type(n)));
320 fprintf (F, "SymC %s ", get_type_name(get_SymConst_type(n)));
321 if (get_SymConst_kind(n) == type_tag)
329 if (!interprocedural_view) fprintf(F, "Proj'");
330 else fprintf(F, "%s", get_irn_opname(n));
334 if (interprocedural_view) {
335 fprintf(F, "%s %s", get_irn_opname(n), get_entity_name(get_irg_ent(get_irn_irg(n))));
341 fprintf (F, "%s", get_irn_opname(n));
348 dump_node_mode (ir_node *n)
350 switch (get_irn_opcode(n)) {
369 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
376 static void dump_node_typeinfo(ir_node *n) {
377 if (!opt_dump_analysed_type_info) return;
378 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
379 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
380 type *tp = get_irn_type(n);
382 fprintf (F, " [%s]", get_type_name(tp));
389 dump_node_nodeattr (ir_node *n)
391 switch (get_irn_opcode(n)) {
393 if (false && interprocedural_view) {
394 fprintf (F, "%s", get_entity_name(get_irg_ent(current_ir_graph)));
398 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
399 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
401 fprintf (F, "%ld", get_Proj_proj(n));
405 fprintf (F, "%ld", get_Filter_proj(n));
408 fprintf (F, "%s", get_entity_name(get_Sel_entity(n)));
411 fprintf (F, "(%s)", get_type_name(get_Cast_type(n)));
414 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
423 dump_node_vcgattr (ir_node *n)
425 switch (get_irn_opcode(n)) {
432 fprintf (F, "color: blue");
435 fprintf (F, "color: lightyellow");
438 fprintf (F, "color: green");
444 fprintf (F, "color: yellow");
447 PRINT_DEFAULT_NODE_ATTR;
452 dump_node_info (ir_node *n) {
454 fprintf (F, " info1: \"");
455 if (opt_dump_pointer_values_to_info)
456 fprintf (F, "addr: %p \n", (void *)n);
457 fprintf (F, "visited: %ld \n", get_irn_visited(n));
460 switch(get_irn_opcode(n)) {
462 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
463 fprintf(F, "start of method of type %s \n", get_type_name(tp));
464 for (i = 0; i < get_method_n_params(tp); ++i)
465 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
468 fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
471 fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
474 fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
475 fprintf(F, " from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
478 type *tp = get_Call_type(n);
479 fprintf(F, "calling method of type %s \n", get_type_name(tp));
480 for (i = 0; i < get_method_n_params(tp); ++i)
481 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
482 for (i = 0; i < get_method_n_ress(tp); ++i)
483 fprintf(F, " resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
486 if (!interprocedural_view) {
487 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
488 fprintf(F, "return in method of type %s \n", get_type_name(tp));
489 for (i = 0; i < get_method_n_ress(tp); ++i)
490 fprintf(F, " res %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
494 type *tp = get_Const_type(n);
495 assert(tp != none_type);
496 fprintf(F, "Const of type %s \n", get_type_name(get_Const_type(n)));
501 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
502 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
503 if (get_irn_type(n) != none_type)
504 fprintf (F, "\nAnalysed type: %s", get_type_name(get_irn_type(n)));
509 /* Returns true if n and pred pos are in different graphs. */
510 static bool pred_in_wrong_graph(ir_node *n, int pos) {
511 ir_node *pred = get_irn_n(n, pos);
513 if (get_irn_irg(n) != get_irn_irg(pred)) return true;
519 bool is_constlike_node(ir_node *n) {
520 ir_op *op = get_irn_op(n);
521 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
525 /* outputs the predecessors of n, that are constants, local. I.e.,
526 generates a copy of the constant for each node called with. */
527 static void dump_const_node_local(ir_node *n) {
529 if (!get_opt_dump_const_local()) return;
530 /* Use visited flag to avoid outputting nodes twice.
531 initialize it first. */
532 for (i = 0; i < get_irn_arity(n); i++) {
533 ir_node *con = get_irn_n(n, i);
534 if (is_constlike_node(con)) {
535 if (pred_in_wrong_graph(n, i)) continue; /* pred not dumped */
536 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
539 for (i = 0; i < get_irn_arity(n); i++) {
540 ir_node *con = get_irn_n(n, i);
541 if (is_constlike_node(con) && irn_not_visited(con)) {
542 if (pred_in_wrong_graph(n, i)) continue; /* pred not dumped */
543 mark_irn_visited(con);
544 /* Generate a new name for the node by appending the names of
546 fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
547 fprintf(F, " label: \"");
548 dump_node_opcode(con);
549 dump_node_mode (con);
550 dump_node_typeinfo(con);
552 dump_node_nodeattr(con);
554 fprintf (F, " %ld", get_irn_node_nr(con));
557 dump_node_vcgattr(con);
565 dump_node (ir_node *n) {
566 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
569 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
573 dump_node_typeinfo(n);
575 dump_node_nodeattr(n);
577 fprintf (F, " %ld", get_irn_node_nr(n));
580 dump_node_vcgattr(n);
583 dump_const_node_local(n);
586 /* dump the edge to the block this node belongs to */
588 dump_ir_block_edge(ir_node *n) {
589 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
590 if (is_no_Block(n)) {
591 fprintf (F, "edge: { sourcename: \"");
593 fprintf (F, "\" targetname: \"");
594 PRINT_NODEID(get_nodes_block(n));
595 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
599 static void print_edge_vcgattr(ir_node *from, int to) {
602 if (dump_backedge_information_flag && is_backedge(from, to))
603 fprintf (F, BACK_EDGE_ATTR);
605 switch (get_irn_opcode(from)) {
607 fprintf (F, CF_EDGE_ATTR);
609 case iro_Start: break;
612 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
613 fprintf (F, CF_EDGE_ATTR);
614 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
615 fprintf (F, MEM_EDGE_ATTR);
618 case iro_EndReg: break;
619 case iro_EndExcept: break;
621 case iro_Break: break;
622 case iro_Cond: break;
625 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
627 case iro_Const: break;
628 case iro_SymConst:break;
631 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
633 case iro_CallBegin: break;
636 case iro_Minus: break;
642 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
650 case iro_Shrs: break;
653 case iro_Conv: break;
655 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
661 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
664 fprintf (F, MEM_EDGE_ATTR);
666 case iro_Tuple: break;
669 switch (get_irn_modecode(from)) {
671 fprintf (F, CF_EDGE_ATTR);
674 fprintf (F, MEM_EDGE_ATTR);
680 case iro_Unknown: break;
687 /* dump edges to our inputs */
689 dump_ir_data_edges(ir_node *n) {
690 int i, visited = get_irn_visited(n);
692 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
695 for (i = 0; i < get_irn_arity(n); i++) {
696 ir_node * pred = get_irn_n(n, i);
698 if ((interprocedural_view && get_irn_visited(pred) < visited))
699 continue; /* pred not dumped */
700 if (dump_backedge_information_flag && is_backedge(n, i))
701 fprintf (F, "backedge: {sourcename: \"");
703 fprintf (F, "edge: {sourcename: \"");
705 fprintf (F, "\" targetname: ");
706 if ((get_opt_dump_const_local()) && is_constlike_node(pred) &&
707 !pred_in_wrong_graph(n, i)) {
708 PRINT_CONSTID(n, pred);
710 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
712 fprintf (F, " label: \"%d\" ", i);
713 print_edge_vcgattr(n, i);
718 /** Dumps a node and its edges but not the block edge
721 dump_node_wo_blockedge (ir_node *n, void* env) {
723 dump_ir_data_edges(n);
726 /** Dumps a node and its edges.
729 dump_whole_node (ir_node *n, void* env) {
730 dump_node_wo_blockedge(n, env);
731 if (!node_floats(n)) dump_ir_block_edge(n);
735 dump_const_node(ir_node *n, void *env) {
736 if (is_Block(n)) return;
737 dump_node_wo_blockedge(n, env);
740 /***********************************************************************/
741 /* the following routines dump the nodes/irgs bracketed to graphs. */
742 /***********************************************************************/
744 /** Dumps a constant expression as entity initializer, array bound ...
746 static void dump_const_expression(ir_node *value) {
747 ir_graph *rem = current_ir_graph;
748 int rem_dump_const_local = dump_const_local;
749 dump_const_local = 0;
750 current_ir_graph = get_const_code_irg();
751 irg_walk(value, dump_const_node, NULL, NULL);
752 /* Decrease visited flag so that we walk with the same flag for the next
753 expresssion. This guarantees that we don't dump the same node twice,
754 as for const expressions cse is performed to save memory. */
755 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
756 current_ir_graph = rem;
757 dump_const_local = rem_dump_const_local;
760 /** Dump a block as graph containing its nodes.
762 * Expects to find nodes belonging to the block as list in its
764 * Dumps the edges of all nodes including itself. */
766 dump_whole_block(ir_node *block) {
768 assert(is_Block(block));
770 fprintf(F, "graph: { title: \"");
772 fprintf(F, "\" label: \"");
773 dump_node_opcode(block);
774 fprintf (F, " %ld", get_irn_node_nr(block));
776 fprintf(F, "\" status:clustered color:%s \n",
777 get_Block_matured(block) ? "yellow" : "red");
779 /* dump the blocks edges */
780 dump_ir_data_edges(block);
782 /* dump the nodes that go into the block */
783 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
785 dump_ir_data_edges(node);
788 /* Close the vcg information for the block */
790 dump_const_node_local(block);
794 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
795 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
797 dump_block_graph (ir_graph *irg) {
799 ir_graph *rem = current_ir_graph;
800 current_ir_graph = irg;
801 ir_node **arr = ird_get_irg_link(irg);
803 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
804 ir_node * node = arr[i];
805 if (is_Block(node)) {
806 /* Dumps the block and all the nodes in the block, which are to
807 be found in Block->link. */
808 dump_whole_block(node);
810 /* Nodes that are not in a Block. */
812 dump_ir_data_edges(node);
816 if (dump_loop_information_flag) dump_loop_info(irg);
818 current_ir_graph = rem;
821 /** Dumps an irg as a graph.
822 * If interprocedural view edges can point to nodes out of this graph.
824 static void dump_graph(ir_graph *irg) {
826 fprintf(F, "graph: { title: \"");
828 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
829 get_entity_name(get_irg_ent(irg)));
831 dump_block_graph (irg);
833 /* Close the vcg information for the irg */
837 /*******************************************************************/
838 /* Basic type and entity nodes and edges. */
839 /*******************************************************************/
841 /* dumps the edges between nodes and their type or entity attributes. */
842 static void dump_node2type_edges (ir_node *n, void *env)
846 switch (get_irn_opcode(n)) {
848 /* @@@ some consts have an entity */
851 if ( (get_SymConst_kind(n) == type_tag)
852 || (get_SymConst_kind(n) == size))
854 PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
858 PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
861 PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
864 PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
867 PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
870 PRINT_NODE_TYPE_EDGE(n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
878 static void print_type_info(type *tp) {
879 if (get_type_state(tp) == layout_undefined) {
880 fprintf(F, "state: layout_undefined\n");
882 fprintf(F, "state: layout_fixed,\n");
884 if (get_type_mode(tp))
885 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
886 fprintf(F, "size: %dB,\n", get_type_size(tp));
889 static void print_typespecific_info(type *tp) {
890 switch (get_type_tpop_code(tp)) {
893 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
907 case tpo_enumeration:
921 static void print_typespecific_vcgattr(type *tp) {
922 switch (get_type_tpop_code(tp)) {
925 if (peculiarity_existent == get_class_peculiarity(tp))
926 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
928 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
932 fprintf (F, " " TYPE_METH_NODE_ATTR);
943 case tpo_enumeration:
956 static void print_type_node(type *tp)
958 fprintf (F, "node: {title: ");
960 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name(tp));
961 fprintf (F, " info1: \"");
963 print_typespecific_info(tp);
965 print_typespecific_vcgattr(tp);
969 #define X(a) case a: fprintf(F, #a); break
970 void dump_entity_node(entity *ent)
972 fprintf (F, "node: {title: \"");
973 PRINT_ENTID(ent); fprintf(F, "\"");
974 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
975 fprintf (F, "label: ");
976 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_entity_name(ent));
977 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
979 fprintf (F, "\nallocation: ");
980 switch (get_entity_allocation(ent)) {
981 X(allocation_dynamic);
982 X(allocation_automatic);
983 X(allocation_static);
984 X(allocation_parameter);
987 fprintf (F, "\nvisibility: ");
988 switch (get_entity_visibility(ent)) {
990 X(visibility_external_visible);
991 X(visibility_external_allocated);
994 fprintf (F, "\nvariability: ");
995 switch (get_entity_variability(ent)) {
996 X(variability_uninitialized);
997 X(variability_initialized);
998 X(variability_part_constant);
999 X(variability_constant);
1002 fprintf (F, "\nvolatility: ");
1003 switch (get_entity_volatility(ent)) {
1004 X(volatility_non_volatile);
1005 X(volatility_is_volatile);
1008 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1009 fprintf(F, "\nname: %s\nld_name: %s",
1010 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1011 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1012 if (is_method_type(get_entity_type(ent))) {
1013 if (get_entity_irg(ent)) /* can be null */
1014 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1016 { fprintf (F, "\nirg = NULL"); }
1018 fprintf(F, "\"\n}\n");
1022 /* dumps a type or entity and it's edges. */
1024 dump_type_info (type_or_ent *tore, void *env) {
1025 int i = 0; /* to shutup gcc */
1027 /* dump this type or entity */
1029 switch (get_kind(tore)) {
1032 entity *ent = (entity *)tore;
1035 dump_entity_node(ent);
1037 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1038 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1039 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1040 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1041 if(is_class_type(get_entity_owner(ent))) {
1042 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1043 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1046 /* attached subgraphs */
1047 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1048 if (is_atomic_entity(ent)) {
1049 value = get_atomic_ent_value(ent);
1051 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
1052 /* DDMN(value); $$$ */
1053 dump_const_expression(value);
1056 if (is_compound_entity(ent)) {
1057 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1058 value = get_compound_ent_value(ent, i);
1060 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
1061 dump_const_expression(value);
1062 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1064 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1065 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1066 get_compound_ent_value_member(ent, i), i);
1075 type *tp = (type *)tore;
1076 print_type_node(tp);
1077 /* and now the edges */
1078 switch (get_type_tpop_code(tp)) {
1081 for (i=0; i < get_class_n_supertypes(tp); i++) {
1082 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1085 for (i=0; i < get_class_n_members(tp); i++) {
1086 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1091 for (i=0; i < get_struct_n_members(tp); i++) {
1092 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1097 for (i = 0; i < get_method_n_params(tp); i++)
1099 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1101 for (i = 0; i < get_method_n_ress(tp); i++)
1103 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1108 for (i = 0; i < get_union_n_members(tp); i++)
1110 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1115 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1116 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1117 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1118 ir_node *upper = get_array_upper_bound(tp, i);
1119 ir_node *lower = get_array_lower_bound(tp, i);
1120 PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1121 PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1122 dump_const_expression(upper);
1123 dump_const_expression(lower);
1127 case tpo_enumeration:
1132 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1140 break; /* case k_type */
1143 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1145 } /* switch kind_or_entity */
1148 /** For dumping class hierarchies.
1149 * Dumps a class type node and a superclass edge.
1150 * If env != null dumps entities of classes and overwrites edges.
1153 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1154 int i = 0; /* to shutup gcc */
1156 /* dump this type or entity */
1157 switch (get_kind(tore)) {
1159 entity *ent = (entity *)tore;
1160 if (get_entity_owner(ent) == get_glob_type()) break;
1161 if ((env) && is_class_type(get_entity_owner(ent))) {
1163 dump_entity_node(ent);
1165 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1166 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1168 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1171 } break; /* case k_entity */
1174 type *tp = (type *)tore;
1175 if (tp == get_glob_type()) break;
1176 switch (get_type_tpop_code(tp)) {
1178 print_type_node(tp);
1179 /* and now the edges */
1180 for (i=0; i < get_class_n_supertypes(tp); i++)
1182 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1188 break; /* case k_type */
1191 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1193 } /* switch kind_or_entity */
1196 /*******************************************************************/
1197 /* dump analysis information that is expressed in graph terms. */
1198 /*******************************************************************/
1200 /* dump out edges */
1202 dump_out_edge (ir_node *n, void* env) {
1204 for (i = 0; i < get_irn_n_outs(n); i++) {
1205 assert(get_irn_out(n, i));
1206 fprintf (F, "edge: {sourcename: \"");
1208 fprintf (F, "\" targetname: \"");
1209 PRINT_NODEID(get_irn_out(n, i));
1210 fprintf (F, "\" color: red linestyle: dashed");
1216 dump_loop_node_edge (ir_loop *loop, int i) {
1218 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
1219 PRINT_NODEID(get_loop_node(loop, i));
1220 fprintf (F, "\" color: green");
1225 dump_loop_son_edge (ir_loop *loop, int i) {
1227 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\" color: darkgreen}\n",
1228 (void *)loop, (void *)get_loop_son(loop, i));
1232 void dump_loops (ir_loop *loop) {
1234 /* dump this loop node */
1235 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
1236 (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1237 /* dump edges to nodes in loop -- only if it is a real loop */
1238 if (get_loop_depth(loop) != 0) {
1239 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1240 dump_loop_node_edge(loop, i);
1243 for (i = 0; i < get_loop_n_sons(loop); i++) {
1244 dump_loops(get_loop_son(loop, i));
1245 dump_loop_son_edge(loop, i);
1250 void dump_loop_info(ir_graph *irg) {
1251 ir_graph *rem = current_ir_graph;
1252 current_ir_graph = irg;
1254 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1256 current_ir_graph = rem;
1260 /************************************************************************/
1261 /* open and close vcg file */
1262 /************************************************************************/
1265 dump_vcg_header(const char *name) {
1275 "graph: { title: \"ir graph of %s\"\n"
1276 "display_edge_labels: %s\n"
1277 "layoutalgorithm: mindepth\n"
1278 "manhattan_edges: yes\n"
1279 "port_sharing: no\n"
1280 "orientation: bottom_to_top\n"
1281 "classname 1: \"Data\"\n"
1282 "classname 2: \"Block\"\n"
1283 "classname 3: \"Entity type\"\n"
1284 "classname 4: \"Entity owner\"\n"
1285 "classname 5: \"Method Param\"\n"
1286 "classname 6: \"Method Res\"\n"
1287 "classname 7: \"Super\"\n"
1288 "classname 8: \"Union\"\n"
1289 "classname 9: \"Points-to\"\n"
1290 "classname 10: \"Array Element Type\"\n"
1291 "classname 11: \"Overwrites\"\n"
1292 "classname 12: \"Member\"\n",
1295 fprintf (F, "\n"); /* a separator */
1298 static void vcg_open (ir_graph *irg, char *suffix) {
1299 char *fname; /* filename to put the vcg information in */
1304 /** open file for vcg graph */
1305 id = get_irg_dump_name(irg);
1306 len = get_id_strlen (id);
1307 cp = get_id_str (id);
1308 if (dump_file_suffix)
1309 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
1311 fname = malloc (len + 5 + strlen(suffix));
1312 strncpy (fname, cp, len); /* copy the filename */
1314 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
1315 strcat (fname, suffix); /* append file suffix */
1316 strcat (fname, ".vcg"); /* append the .vcg suffix */
1317 F = fopen (fname, "w"); /* open file for writing */
1319 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1321 dump_vcg_header(cp);
1324 static void vcg_open_name (const char *name) {
1325 char *fname; /* filename to put the vcg information in */
1328 /** open file for vcg graph */
1330 fname = malloc (len + 5);
1331 if (dump_file_suffix)
1332 fname = malloc (len + 5 + strlen(dump_file_suffix));
1334 fname = malloc (len + 5);
1335 strcpy (fname, name); /* copy the filename */
1336 if (dump_file_suffix) strcat (fname, dump_file_suffix);
1337 strcat (fname, ".vcg"); /* append the .vcg suffix */
1338 F = fopen (fname, "w"); /* open file for writing */
1340 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1343 dump_vcg_header(name);
1348 fprintf (F, "}\n"); /* print footer */
1349 fclose (F); /* close vcg file */
1352 /************************************************************************/
1353 /************************************************************************/
1354 /* Routines that dump all or parts of the firm representation to a file */
1355 /************************************************************************/
1356 /************************************************************************/
1358 /************************************************************************/
1359 /* Dump ir graphs, differnt formats and additional information. */
1360 /************************************************************************/
1362 /** Routine to dump a graph, blocks as conventional nodes.
1365 dump_ir_graph (ir_graph *irg)
1369 rem = current_ir_graph;
1370 current_ir_graph = irg;
1372 if (interprocedural_view) suffix = "-pure-ip";
1373 else suffix = "-pure";
1374 vcg_open (irg, suffix);
1376 /* walk over the graph */
1377 /* dump_whole_node must be called in post visiting predecessors */
1378 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1380 /* dump the out edges in a separate walk */
1381 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1382 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1387 current_ir_graph = rem;
1392 dump_ir_block_graph (ir_graph *irg)
1397 construct_block_lists(irg);
1399 if (interprocedural_view) suffix = "-ip";
1401 vcg_open (irg, suffix);
1403 for (i = 0; i < get_irp_n_irgs(); i++) {
1404 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1406 dump_graph(get_irp_irg(i));
1414 /** dumps a graph with type information
1417 dump_ir_graph_w_types (ir_graph *irg)
1420 rem = current_ir_graph;
1422 current_ir_graph = irg;
1424 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1425 else suffix = "-pure-wtypes";
1426 vcg_open (irg, suffix);
1428 /* dump common ir graph */
1429 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1430 /* dump type info */
1431 type_walk_irg(irg, dump_type_info, NULL, NULL);
1432 inc_irg_visited(get_const_code_irg());
1433 /* dump edges from graph to type info */
1434 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1437 current_ir_graph = rem;
1441 dump_ir_block_graph_w_types (ir_graph *irg)
1445 ir_graph *rem = current_ir_graph;
1447 if (interprocedural_view) suffix = "-wtypes-ip";
1448 else suffix = "-wtypes";
1449 vcg_open (irg, suffix);
1451 /* dump common blocked ir graph */
1452 construct_block_lists(irg);
1454 for (i = 0; i < get_irp_n_irgs(); i++) {
1455 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1457 dump_graph(get_irp_irg(i));
1462 /* dump type info */
1463 current_ir_graph = irg;
1464 type_walk_irg(irg, dump_type_info, NULL, NULL);
1465 inc_irg_visited(get_const_code_irg());
1467 /* dump edges from graph to type info */
1468 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1470 current_ir_graph = rem;
1474 /***********************************************************************/
1475 /* The following routines dump a control flow graph. */
1476 /***********************************************************************/
1479 dump_block_to_cfg (ir_node *block, void *env) {
1483 if (is_Block(block)) {
1484 /* This is a block. Dump a node for the block. */
1485 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1486 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1487 PRINT_NODEID(block);
1489 if (dump_dominator_information_flag)
1490 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1492 /* Dump the edges */
1493 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1494 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1495 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1496 fprintf (F, "edge: { sourcename: \"");
1497 PRINT_NODEID(block);
1498 fprintf (F, "\" targetname: \"");
1500 fprintf (F, "\"}\n");
1503 /* Dump dominator edge */
1504 if (dump_dominator_information_flag && get_Block_idom(block)) {
1505 pred = get_Block_idom(block);
1506 fprintf (F, "edge: { sourcename: \"");
1507 PRINT_NODEID(block);
1508 fprintf (F, "\" targetname: \"");
1510 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1516 dump_cfg (ir_graph *irg)
1518 ir_graph *rem = current_ir_graph;
1519 int ddif = dump_dominator_information_flag;
1520 int ipv = interprocedural_view;
1521 current_ir_graph = irg;
1522 vcg_open (irg, "-cfg");
1524 if (interprocedural_view) {
1525 printf("Warning: dumping cfg not in interprocedural view!\n");
1526 interprocedural_view = 0;
1529 if (get_irg_dom_state(irg) != dom_consistent)
1530 dump_dominator_information_flag = 0;
1532 /* walk over the blocks in the graph */
1533 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1534 dump_node (get_irg_bad(irg));
1536 dump_dominator_information_flag = ddif;
1537 interprocedural_view = ipv;
1539 current_ir_graph = rem;
1544 /* Dump all irgs in interprocedural view to a single file. */
1545 void dump_all_cg_block_graph(void) {
1547 int rem_view = interprocedural_view;
1548 interprocedural_view = 1;
1549 vcg_open_name ("All_graphs");
1551 /* collect nodes in all irgs reachable in call graph*/
1552 for (i = 0; i < get_irp_n_irgs(); i++)
1553 ird_set_irg_link(get_irp_irg(i), NULL);
1555 cg_walk(clear_link, collect_node, NULL);
1557 /* dump all graphs */
1558 for (i = 0; i < get_irp_n_irgs(); i++) {
1559 current_ir_graph = get_irp_irg(i);
1560 dump_graph(current_ir_graph);
1561 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1565 interprocedural_view = rem_view;
1568 /***********************************************************************/
1569 /* the following routines dumps type information without any ir nodes. */
1570 /***********************************************************************/
1573 dump_type_graph (ir_graph *irg)
1576 rem = current_ir_graph;
1577 current_ir_graph = irg;
1579 vcg_open (irg, "-type");
1581 /* walk over the blocks in the graph */
1582 type_walk_irg(irg, dump_type_info, NULL, NULL);
1583 /* The walker for the const code can be called several times for the
1584 same (sub) experssion. So that no nodes are dumped several times
1585 we decrease the visited flag of the corresponding graph after each
1586 walk. So now increase it finally. */
1587 inc_irg_visited(get_const_code_irg());
1590 current_ir_graph = rem;
1594 dump_all_types (void)
1596 vcg_open_name ("All_types");
1597 type_walk(dump_type_info, NULL, NULL);
1598 inc_irg_visited(get_const_code_irg());
1603 dump_class_hierarchy (bool entities)
1605 vcg_open_name ("class_hierarchy");
1607 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1609 type_walk(dump_class_hierarchy_node, NULL, NULL);
1613 /***********************************************************************/
1614 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1616 /* dump_ir_block_graph */
1618 /* dump_type_graph */
1619 /* dump_ir_graph_w_types */
1620 /***********************************************************************/
1622 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1624 for (i=0; i < get_irp_n_irgs(); i++) {
1625 dmp_grph(get_irp_irg(i));