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 funcions. */
119 /*******************************************************************/
121 static void clear_link(ir_node * node, void * env) {
122 set_irn_link(node, NULL);
125 static int node_floats(ir_node *n) {
126 return ((get_op_pinned(get_irn_op(n)) == floats) &&
127 (get_irg_pinned(current_ir_graph) == floats));
130 static ident *get_irg_dump_name (ir_graph *irg) {
131 entity *ent = get_irg_ent(irg);
132 if (ent->ld_name) return ent->ld_name;
136 static void collect_node(ir_node * node, void *env) {
139 || get_irn_op(node) == op_Bad
140 || get_irn_op(node) == op_Unknown) {
141 ir_node ** arr = (ir_node **) get_irg_link(get_irn_irg(node));
142 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
143 ARR_APP1(ir_node *, arr, node);
144 set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
146 ir_node * block = get_nodes_block(node);
147 set_irn_link(node, get_irn_link(block));
148 set_irn_link(block, node);
152 /** Construct lists to walk ir block-wise.
154 * Collects all blocks, nodes not pinned,
155 * Bad and Unknown into a flexible array in link field of
156 * irg they belong to. Sets the irg link field to NULL in all
157 * graphs not visited.
158 * Free the list with DEL_ARR_F. */
159 static ir_node ** construct_block_lists(ir_graph *irg) {
161 ir_graph *rem = current_ir_graph;
162 current_ir_graph = irg;
164 for (i = 0; i < get_irp_n_irgs(); i++)
165 set_irg_link(get_irp_irg(i), NULL);
167 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
169 current_ir_graph = rem;
170 return get_irg_link(irg);
173 /*******************************************************************/
174 /* flags to steer output */
175 /*******************************************************************/
177 /* A compiler option to turn off edge labels */
179 /* A compiler option to turn off dumping values of constant entities */
180 int const_entities = 1;
181 /* A compiler option to dump the keep alive edges */
182 int dump_keepalive = 0;
183 /* Compiler options to dump analysis information in dump_ir_graph */
184 int dump_out_edge_flag = 0;
185 int dump_dominator_information_flag = 0;
186 int dump_loop_information_flag = 0;
187 int dump_backedge_information_flag = 1;
188 int dump_const_local = 0;
189 bool opt_dump_analysed_type_info = 1;
191 INLINE bool get_opt_dump_const_local(void) {
192 if (!dump_out_edge_flag && !dump_loop_information_flag)
193 return dump_const_local;
198 /* To turn off display of edge labels. Edge labels offen cause xvcg to
199 abort with a segmentation fault. */
200 void turn_off_edge_labels(void) {
204 void dump_consts_local(bool b) {
205 dump_const_local = b;
208 void turn_off_constant_entity_values(void) {
212 void dump_keepalive_edges(bool b) {
216 bool get_opt_dump_keepalive_edges(void) {
217 return dump_keepalive;
220 void dump_out_edges(void) {
221 dump_out_edge_flag = 1;
224 void dump_dominator_information(void) {
225 dump_dominator_information_flag = 1;
228 void dump_loop_information(void) {
229 dump_loop_information_flag = 1;
232 void dont_dump_loop_information(void) {
233 dump_loop_information_flag = 0;
236 void dump_backedge_information(bool b) {
237 dump_backedge_information_flag = b;
240 /* Dump the information of type field specified in ana/irtypeinfo.h.
241 * If the flag is set, the type name is output in [] in the node label,
242 * else it is output as info.
244 void dump_analysed_type_info(bool b) {
245 opt_dump_analysed_type_info = b;
250 /*******************************************************************/
251 /* Routines to dump information about a single ir node. */
252 /*******************************************************************/
255 dump_node_opcode (ir_node *n)
259 switch(get_irn_opcode(n)) {
263 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
264 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
269 if (get_SymConst_kind(n) == linkage_ptr_info) {
270 /* don't use get_SymConst_ptr_info as it mangles the name. */
271 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
273 assert(get_kind(get_SymConst_type(n)) == k_type);
274 assert(get_type_ident(get_SymConst_type(n)));
275 fprintf (F, "SymC %s ", get_type_name(get_SymConst_type(n)));
276 if (get_SymConst_kind(n) == type_tag)
284 if (!interprocedural_view) fprintf(F, "Proj'");
285 else fprintf(F, "%s", get_irn_opname(n));
289 if (interprocedural_view) {
290 fprintf(F, "%s %s", get_irn_opname(n), get_entity_name(get_irg_ent(get_irn_irg(n))));
296 fprintf (F, "%s", get_irn_opname(n));
303 dump_node_mode (ir_node *n)
305 switch (get_irn_opcode(n)) {
324 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
331 static void dump_node_typeinfo(ir_node *n) {
332 if (!opt_dump_analysed_type_info) return;
333 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
334 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
335 type *tp = get_irn_type(n);
337 fprintf (F, " [%s]", get_type_name(tp));
344 dump_node_nodeattr (ir_node *n)
346 switch (get_irn_opcode(n)) {
348 if (false && interprocedural_view) {
349 fprintf (F, "%s", get_entity_name(get_irg_ent(current_ir_graph)));
353 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
354 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
356 fprintf (F, "%ld", get_Proj_proj(n));
360 fprintf (F, "%ld", get_Filter_proj(n));
363 fprintf (F, "%s", get_entity_name(get_Sel_entity(n)));
366 fprintf (F, "(%s)", get_type_name(get_Cast_type(n)));
369 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
378 dump_node_vcgattr (ir_node *n)
380 switch (get_irn_opcode(n)) {
387 fprintf (F, "color: blue");
390 fprintf (F, "color: lightyellow");
393 fprintf (F, "color: green");
399 fprintf (F, "color: yellow");
402 PRINT_DEFAULT_NODE_ATTR;
407 dump_node_info (ir_node *n) {
409 fprintf (F, " info1: \"");
410 fprintf (F, "visited: %ld \n", get_irn_visited(n));
413 switch(get_irn_opcode(n)) {
415 type *tp = get_entity_type(get_irg_ent(get_Start_irg(n)));
416 fprintf(F, "start of method of type %s \n", get_type_name(tp));
417 for (i = 0; i < get_method_n_params(tp); ++i)
418 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
421 fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
424 fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
427 fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
428 fprintf(F, " from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
431 type *tp = get_Call_type(n);
432 fprintf(F, "calling method of type %s \n", get_type_name(tp));
433 for (i = 0; i < get_method_n_params(tp); ++i)
434 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
435 for (i = 0; i < get_method_n_ress(tp); ++i)
436 fprintf(F, " resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
439 if (!interprocedural_view) {
440 type *tp = get_entity_type(get_irg_ent(current_ir_graph));
441 fprintf(F, "return in method of type %s \n", get_type_name(tp));
442 for (i = 0; i < get_method_n_ress(tp); ++i)
443 fprintf(F, " res %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
447 type *tp = get_Const_type(n);
448 assert(tp != none_type);
449 fprintf(F, "Const of type %s \n", get_type_name(get_Const_type(n)));
454 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
455 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent )
456 if (get_irn_type(n) != none_type)
457 fprintf (F, "\nAnalysed type: %s", get_type_name(get_irn_type(n)));
463 /* Returns true if n and pred pos are in different graphs. */
464 static bool pred_in_wrong_graph(ir_node *n, int pos) {
465 ir_node *pred = get_irn_n(n, pos);
467 if (get_irn_irg(n) != get_irn_irg(pred)) return true;
473 bool is_constlike_node(ir_node *n) {
474 ir_op *op = get_irn_op(n);
475 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
479 /* outputs the predecessors of n, that are constants, local. I.e.,
480 generates a copy of the constant for each node called with. */
481 static void dump_const_node_local(ir_node *n) {
483 if (!get_opt_dump_const_local()) return;
484 /* Use visited flag to avoid outputting nodes twice.
485 initialize it first. */
486 for (i = 0; i < get_irn_arity(n); i++) {
487 ir_node *con = get_irn_n(n, i);
488 if (is_constlike_node(con)) {
489 if (pred_in_wrong_graph(n, i)) continue; /* pred not dumped */
490 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
493 for (i = 0; i < get_irn_arity(n); i++) {
494 ir_node *con = get_irn_n(n, i);
495 if (is_constlike_node(con) && irn_not_visited(con)) {
496 if (pred_in_wrong_graph(n, i)) continue; /* pred not dumped */
497 mark_irn_visited(con);
498 /* Generate a new name for the node by appending the names of
500 fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
501 fprintf(F, " label: \"");
502 dump_node_opcode(con);
503 dump_node_mode (con);
504 dump_node_typeinfo(con);
506 dump_node_nodeattr(con);
508 fprintf (F, " %ld", get_irn_node_nr(con));
511 dump_node_vcgattr(con);
519 dump_node (ir_node *n) {
520 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
523 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
527 dump_node_typeinfo(n);
529 dump_node_nodeattr(n);
531 fprintf (F, " %ld", get_irn_node_nr(n));
534 dump_node_vcgattr(n);
537 dump_const_node_local(n);
540 /* dump the edge to the block this node belongs to */
542 dump_ir_block_edge(ir_node *n) {
543 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
544 if (is_no_Block(n)) {
545 fprintf (F, "edge: { sourcename: \"");
547 fprintf (F, "\" targetname: \"");
548 PRINT_NODEID(get_nodes_block(n));
549 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
553 static void print_edge_vcgattr(ir_node *from, int to) {
556 if (dump_backedge_information_flag && is_backedge(from, to))
557 fprintf (F, BACK_EDGE_ATTR);
559 switch (get_irn_opcode(from)) {
561 fprintf (F, CF_EDGE_ATTR);
563 case iro_Start: break;
566 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
567 fprintf (F, CF_EDGE_ATTR);
568 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
569 fprintf (F, MEM_EDGE_ATTR);
572 case iro_EndReg: break;
573 case iro_EndExcept: break;
575 case iro_Break: break;
576 case iro_Cond: break;
579 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
581 case iro_Const: break;
582 case iro_SymConst:break;
585 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
587 case iro_CallBegin: break;
590 case iro_Minus: break;
596 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
604 case iro_Shrs: break;
607 case iro_Conv: break;
609 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
615 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
618 fprintf (F, MEM_EDGE_ATTR);
620 case iro_Tuple: break;
623 switch (get_irn_modecode(from)) {
625 fprintf (F, CF_EDGE_ATTR);
628 fprintf (F, MEM_EDGE_ATTR);
634 case iro_Unknown: break;
641 /* dump edges to our inputs */
643 dump_ir_data_edges(ir_node *n) {
644 int i, visited = get_irn_visited(n);
646 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
649 for (i = 0; i < get_irn_arity(n); i++) {
650 ir_node * pred = get_irn_n(n, i);
652 if ((interprocedural_view && get_irn_visited(pred) < visited))
653 continue; /* pred not dumped */
654 if (dump_backedge_information_flag && is_backedge(n, i))
655 fprintf (F, "backedge: {sourcename: \"");
657 fprintf (F, "edge: {sourcename: \"");
659 fprintf (F, "\" targetname: ");
660 if ((get_opt_dump_const_local()) && is_constlike_node(pred) &&
661 !pred_in_wrong_graph(n, i)) {
662 PRINT_CONSTID(n, pred);
664 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
666 fprintf (F, " label: \"%d\" ", i);
667 print_edge_vcgattr(n, i);
672 /** Dumps a node and its edges but not the block edge
675 dump_node_wo_blockedge (ir_node *n, void* env) {
677 dump_ir_data_edges(n);
680 /** Dumps a node and its edges.
683 dump_whole_node (ir_node *n, void* env) {
684 dump_node_wo_blockedge(n, env);
685 if (!node_floats(n)) dump_ir_block_edge(n);
689 dump_const_node(ir_node *n, void *env) {
690 if (is_Block(n)) return;
691 dump_node_wo_blockedge(n, env);
694 /***********************************************************************/
695 /* the following routines dump the nodes/irgs bracketed to graphs. */
696 /***********************************************************************/
698 /** Dumps a constant expression as entity initializer, array bound ...
700 static void dump_const_expression(ir_node *value) {
701 ir_graph *rem = current_ir_graph;
702 int rem_dump_const_local = dump_const_local;
703 dump_const_local = 0;
704 current_ir_graph = get_const_code_irg();
705 irg_walk(value, dump_const_node, NULL, NULL);
706 /* Decrease visited flag so that we walk with the same flag for the next
707 expresssion. This guarantees that we don't dump the same node twice,
708 as for const expressions cse is performed to save memory. */
709 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
710 current_ir_graph = rem;
711 dump_const_local = rem_dump_const_local;
714 /** Dump a block as graph containing its nodes.
716 * Expects to find nodes belonging to the block as list in its
718 * Dumps the edges of all nodes including itself. */
720 dump_whole_block(ir_node *block) {
722 assert(is_Block(block));
724 fprintf(F, "graph: { title: \"");
726 fprintf(F, "\" label: \"");
727 dump_node_opcode(block);
728 fprintf (F, " %ld", get_irn_node_nr(block));
730 fprintf(F, "\" status:clustered color:%s \n",
731 get_Block_matured(block) ? "yellow" : "red");
733 /* dump the blocks edges */
734 dump_ir_data_edges(block);
736 /* dump the nodes that go into the block */
737 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
739 dump_ir_data_edges(node);
742 /* Close the vcg information for the block */
744 dump_const_node_local(block);
748 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
749 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
751 dump_block_graph (ir_graph *irg) {
753 ir_graph *rem = current_ir_graph;
754 current_ir_graph = irg;
755 ir_node **arr = get_irg_link(irg);
757 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
758 ir_node * node = arr[i];
759 if (is_Block(node)) {
760 /* Dumps the block and all the nodes in the block, which are to
761 be found in Block->link. */
762 dump_whole_block(node);
764 /* Nodes that are not in a Block. */
766 dump_ir_data_edges(node);
770 if (dump_loop_information_flag) dump_loop_info(irg);
772 current_ir_graph = rem;
775 /** Dumps an irg as a graph.
776 * If interprocedural view edges can point to nodes out of this graph.
778 static void dump_graph(ir_graph *irg) {
780 fprintf(F, "graph: { title: \"%p\" label: \"%s\" status:clustered color:white \n",
781 (void*) irg, get_entity_name(get_irg_ent(irg)));
783 dump_block_graph (irg);
785 /* Close the vcg information for the irg */
789 /*******************************************************************/
790 /* Basic type and entity nodes and edges. */
791 /*******************************************************************/
793 /* dumps the edges between nodes and their type or entity attributes. */
794 static void dump_node2type_edges (ir_node *n, void *env)
798 switch (get_irn_opcode(n)) {
800 /* @@@ some consts have an entity */
803 if ( (get_SymConst_kind(n) == type_tag)
804 || (get_SymConst_kind(n) == size))
806 PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
810 PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
813 PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
816 PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
819 PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
822 PRINT_NODE_TYPE_EDGE(n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
830 static void print_type_info(type *tp) {
831 if (get_type_state(tp) == layout_undefined) {
832 fprintf(F, "state: layout_undefined\n");
834 fprintf(F, "state: layout_fixed,\n");
836 if (get_type_mode(tp))
837 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
838 fprintf(F, "size: %dB,\n", get_type_size(tp));
842 static void print_typespecific_info(type *tp) {
843 switch (get_type_tpop_code(tp)) {
846 if (peculiarity_existent == get_class_peculiarity(tp))
847 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
849 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
853 fprintf (F, " " TYPE_METH_NODE_ATTR);
864 case tpo_enumeration:
877 static void print_type_node(type *tp)
879 fprintf (F, "node: {title: ");
881 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name(tp));
882 fprintf (F, " info1: \"");
885 print_typespecific_info(tp);
889 #define X(a) case a: fprintf(F, #a); break
890 void dump_entity_node(entity *ent)
892 fprintf (F, "node: {title: \"");
893 PRINT_ENTID(ent); fprintf(F, "\"");
894 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
895 fprintf (F, "label: ");
896 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_entity_name(ent));
897 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
899 fprintf (F, "\nallocation: ");
900 switch (get_entity_allocation(ent)) {
901 X(allocation_dynamic);
902 X(allocation_automatic);
903 X(allocation_static);
904 X(allocation_parameter);
907 fprintf (F, "\nvisibility: ");
908 switch (get_entity_visibility(ent)) {
910 X(visibility_external_visible);
911 X(visibility_external_allocated);
914 fprintf (F, "\nvariability: ");
915 switch (get_entity_variability(ent)) {
916 X(variability_uninitialized);
917 X(variability_initialized);
918 X(variability_part_constant);
919 X(variability_constant);
922 fprintf (F, "\nvolatility: ");
923 switch (get_entity_volatility(ent)) {
924 X(volatility_non_volatile);
925 X(volatility_is_volatile);
928 fprintf (F, "\npeculiarity: ");
929 switch (get_entity_peculiarity(ent)) {
930 X(peculiarity_description);
931 X(peculiarity_inherited);
932 X(peculiarity_existent);
934 fprintf(F, "\nname: %s\nld_name: %s",
935 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
936 fprintf(F, "\noffset: %d", get_entity_offset(ent));
937 if (is_method_type(get_entity_type(ent))) {
938 if (get_entity_irg(ent)) /* can be null */
939 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
941 { fprintf (F, "\nirg = NULL"); }
943 fprintf(F, "\"\n}\n");
947 /* dumps a type or entity and it's edges. */
949 dump_type_info (type_or_ent *tore, void *env) {
950 int i = 0; /* to shutup gcc */
952 /* dump this type or entity */
954 switch (get_kind(tore)) {
957 entity *ent = (entity *)tore;
960 dump_entity_node(ent);
962 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
963 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
964 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
965 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
966 if(is_class_type(get_entity_owner(ent))) {
967 for(i = 0; i < get_entity_n_overwrites(ent); i++){
968 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
971 /* attached subgraphs */
972 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
973 if (is_atomic_entity(ent)) {
974 value = get_atomic_ent_value(ent);
976 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
977 /* DDMN(value); $$$ */
978 dump_const_expression(value);
981 if (is_compound_entity(ent)) {
982 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
983 value = get_compound_ent_value(ent, i);
985 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
986 dump_const_expression(value);
987 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
989 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
990 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
991 get_compound_ent_value_member(ent, i), i);
1000 type *tp = (type *)tore;
1001 print_type_node(tp);
1002 /* and now the edges */
1003 switch (get_type_tpop_code(tp)) {
1006 for (i=0; i < get_class_n_supertypes(tp); i++) {
1007 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1010 for (i=0; i < get_class_n_members(tp); i++) {
1011 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1016 for (i=0; i < get_struct_n_members(tp); i++) {
1017 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1022 for (i = 0; i < get_method_n_params(tp); i++)
1024 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1026 for (i = 0; i < get_method_n_ress(tp); i++)
1028 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1033 for (i = 0; i < get_union_n_members(tp); i++)
1035 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1040 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1041 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1042 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1043 ir_node *upper = get_array_upper_bound(tp, i);
1044 ir_node *lower = get_array_lower_bound(tp, i);
1045 PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1046 PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1047 dump_const_expression(upper);
1048 dump_const_expression(lower);
1052 case tpo_enumeration:
1057 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1065 break; /* case k_type */
1068 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1070 } /* switch kind_or_entity */
1073 /** For dumping class hierarchies.
1074 * Dumps a class type node and a superclass edge.
1075 * If env != null dumps entities of classes and overwrites edges.
1078 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1079 int i = 0; /* to shutup gcc */
1081 /* dump this type or entity */
1082 switch (get_kind(tore)) {
1084 entity *ent = (entity *)tore;
1085 if (get_entity_owner(ent) == get_glob_type()) break;
1086 if ((env) && is_class_type(get_entity_owner(ent))) {
1088 dump_entity_node(ent);
1090 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1091 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1093 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1096 } break; /* case k_entity */
1099 type *tp = (type *)tore;
1100 if (tp == get_glob_type()) break;
1101 switch (get_type_tpop_code(tp)) {
1103 print_type_node(tp);
1104 /* and now the edges */
1105 for (i=0; i < get_class_n_supertypes(tp); i++)
1107 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1113 break; /* case k_type */
1116 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1118 } /* switch kind_or_entity */
1121 /*******************************************************************/
1122 /* dump analysis information that is expressed in graph terms. */
1123 /*******************************************************************/
1125 /* dump out edges */
1127 dump_out_edge (ir_node *n, void* env) {
1129 for (i = 0; i < get_irn_n_outs(n); i++) {
1130 assert(get_irn_out(n, i));
1131 fprintf (F, "edge: {sourcename: \"");
1133 fprintf (F, "\" targetname: \"");
1134 PRINT_NODEID(get_irn_out(n, i));
1135 fprintf (F, "\" color: red linestyle: dashed");
1141 dump_loop_node_edge (ir_loop *loop, int i) {
1143 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
1144 PRINT_NODEID(get_loop_node(loop, i));
1145 fprintf (F, "\" color: green");
1150 dump_loop_son_edge (ir_loop *loop, int i) {
1152 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\" color: darkgreen}\n",
1153 (void *)loop, (void *)get_loop_son(loop, i));
1157 void dump_loops (ir_loop *loop) {
1159 /* dump this loop node */
1160 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
1161 (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1162 /* dump edges to nodes in loop -- only if it is a real loop */
1163 if (get_loop_depth(loop) != 0) {
1164 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1165 dump_loop_node_edge(loop, i);
1168 for (i = 0; i < get_loop_n_sons(loop); i++) {
1169 dump_loops(get_loop_son(loop, i));
1170 dump_loop_son_edge(loop, i);
1175 void dump_loop_info(ir_graph *irg) {
1176 ir_graph *rem = current_ir_graph;
1177 current_ir_graph = irg;
1179 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1181 current_ir_graph = rem;
1185 /************************************************************************/
1186 /* open and close vcg file */
1187 /************************************************************************/
1190 dump_vcg_header(const char *name) {
1200 "graph: { title: \"ir graph of %s\"\n"
1201 "display_edge_labels: %s\n"
1202 "layoutalgorithm: mindepth\n"
1203 "manhattan_edges: yes\n"
1204 "port_sharing: no\n"
1205 "orientation: bottom_to_top\n"
1206 "classname 1: \"Data\"\n"
1207 "classname 2: \"Block\"\n"
1208 "classname 3: \"Entity type\"\n"
1209 "classname 4: \"Entity owner\"\n"
1210 "classname 5: \"Method Param\"\n"
1211 "classname 6: \"Method Res\"\n"
1212 "classname 7: \"Super\"\n"
1213 "classname 8: \"Union\"\n"
1214 "classname 9: \"Points-to\"\n"
1215 "classname 10: \"Array Element Type\"\n"
1216 "classname 11: \"Overwrites\"\n"
1217 "classname 12: \"Member\"\n",
1220 fprintf (F, "\n"); /* a separator */
1223 static void vcg_open (ir_graph *irg, char *suffix) {
1224 char *fname; /* filename to put the vcg information in */
1229 /** open file for vcg graph */
1230 id = get_irg_dump_name(irg);
1231 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
1232 len = get_id_strlen (id);
1233 cp = get_id_str (id);
1234 if (dump_file_suffix)
1235 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
1237 fname = malloc (len + 5 + strlen(suffix));
1238 strncpy (fname, cp, len); /* copy the filename */
1240 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
1241 strcat (fname, suffix); /* append file suffix */
1242 strcat (fname, ".vcg"); /* append the .vcg suffix */
1243 F = fopen (fname, "w"); /* open file for writing */
1245 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1247 dump_vcg_header(cp);
1250 static void vcg_open_name (const char *name) {
1251 char *fname; /* filename to put the vcg information in */
1254 /** open file for vcg graph */
1256 fname = malloc (len + 5);
1257 if (dump_file_suffix)
1258 fname = malloc (len + 5 + strlen(dump_file_suffix));
1260 fname = malloc (len + 5);
1261 strcpy (fname, name); /* copy the filename */
1262 if (dump_file_suffix) strcat (fname, dump_file_suffix);
1263 strcat (fname, ".vcg"); /* append the .vcg suffix */
1264 F = fopen (fname, "w"); /* open file for writing */
1266 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1269 dump_vcg_header(name);
1274 fprintf (F, "}\n"); /* print footer */
1275 fclose (F); /* close vcg file */
1278 /************************************************************************/
1279 /************************************************************************/
1280 /* Routines that dump all or parts of the firm representation to a file */
1281 /************************************************************************/
1282 /************************************************************************/
1284 /************************************************************************/
1285 /* Dump ir graphs, differnt formats and additional information. */
1286 /************************************************************************/
1288 /** Routine to dump a graph, blocks as conventional nodes.
1291 dump_ir_graph (ir_graph *irg)
1295 rem = current_ir_graph;
1296 current_ir_graph = irg;
1298 if (interprocedural_view) suffix = "-pure-ip";
1299 else suffix = "-pure";
1300 vcg_open (irg, suffix);
1302 /* walk over the graph */
1303 /* dump_whole_node must be called in post visiting predecessors */
1304 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1306 /* dump the out edges in a separate walk */
1307 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1308 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1313 current_ir_graph = rem;
1318 dump_ir_block_graph (ir_graph *irg)
1323 construct_block_lists(irg);
1325 if (interprocedural_view) suffix = "-ip";
1327 vcg_open (irg, suffix);
1329 for (i = 0; i < get_irp_n_irgs(); i++) {
1330 ir_node **arr = get_irg_link(get_irp_irg(i));
1332 dump_graph(get_irp_irg(i));
1340 /** dumps a graph with type information
1343 dump_ir_graph_w_types (ir_graph *irg)
1346 rem = current_ir_graph;
1348 current_ir_graph = irg;
1350 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1351 else suffix = "-pure-wtypes";
1352 vcg_open (irg, suffix);
1354 /* dump common ir graph */
1355 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1356 /* dump type info */
1357 type_walk_irg(irg, dump_type_info, NULL, NULL);
1358 inc_irg_visited(get_const_code_irg());
1359 /* dump edges from graph to type info */
1360 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1363 current_ir_graph = rem;
1367 dump_ir_block_graph_w_types (ir_graph *irg)
1371 ir_graph *rem = current_ir_graph;
1373 if (interprocedural_view) suffix = "-wtypes-ip";
1374 else suffix = "-wtypes";
1375 vcg_open (irg, suffix);
1377 /* dump common blocked ir graph */
1378 construct_block_lists(irg);
1380 for (i = 0; i < get_irp_n_irgs(); i++) {
1381 ir_node **arr = get_irg_link(get_irp_irg(i));
1383 dump_graph(get_irp_irg(i));
1388 /* dump type info */
1389 current_ir_graph = irg;
1390 type_walk_irg(irg, dump_type_info, NULL, NULL);
1391 inc_irg_visited(get_const_code_irg());
1393 /* dump edges from graph to type info */
1394 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1396 current_ir_graph = rem;
1400 /***********************************************************************/
1401 /* The following routines dump a control flow graph. */
1402 /***********************************************************************/
1405 dump_block_to_cfg (ir_node *block, void *env) {
1409 if (is_Block(block)) {
1410 /* This is a block. Dump a node for the block. */
1411 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1412 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1413 PRINT_NODEID(block);
1415 if (dump_dominator_information_flag)
1416 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1418 /* Dump the edges */
1419 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1420 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1421 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1422 fprintf (F, "edge: { sourcename: \"");
1423 PRINT_NODEID(block);
1424 fprintf (F, "\" targetname: \"");
1426 fprintf (F, "\"}\n");
1429 /* Dump dominator edge */
1430 if (dump_dominator_information_flag && get_Block_idom(block)) {
1431 pred = get_Block_idom(block);
1432 fprintf (F, "edge: { sourcename: \"");
1433 PRINT_NODEID(block);
1434 fprintf (F, "\" targetname: \"");
1436 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1442 dump_cfg (ir_graph *irg)
1444 ir_graph *rem = current_ir_graph;
1445 int ddif = dump_dominator_information_flag;
1446 current_ir_graph = irg;
1447 vcg_open (irg, "-cfg");
1449 if (get_irg_dom_state(irg) != dom_consistent)
1450 dump_dominator_information_flag = 0;
1452 /* walk over the blocks in the graph */
1453 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1454 dump_node (get_irg_bad(irg));
1456 dump_dominator_information_flag = ddif;
1458 current_ir_graph = rem;
1463 /* Dump all irgs in interprocedural view to a single file. */
1464 void dump_all_cg_block_graph(void) {
1466 int rem_view = interprocedural_view;
1467 interprocedural_view = 1;
1468 vcg_open_name ("All_graphs");
1470 /* collect nodes in all irgs reachable in call graph*/
1471 for (i = 0; i < get_irp_n_irgs(); i++)
1472 set_irg_link(get_irp_irg(i), NULL);
1474 cg_walk(clear_link, collect_node, NULL);
1476 /* dump all graphs */
1477 for (i = 0; i < get_irp_n_irgs(); i++) {
1478 current_ir_graph = get_irp_irg(i);
1479 dump_graph(current_ir_graph);
1480 DEL_ARR_F(get_irg_link(current_ir_graph));
1484 interprocedural_view = rem_view;
1487 /***********************************************************************/
1488 /* the following routines dumps type information without any ir nodes. */
1489 /***********************************************************************/
1492 dump_type_graph (ir_graph *irg)
1495 rem = current_ir_graph;
1496 current_ir_graph = irg;
1498 vcg_open (irg, "-type");
1500 /* walk over the blocks in the graph */
1501 type_walk_irg(irg, dump_type_info, NULL, NULL);
1502 /* The walker for the const code can be called several times for the
1503 same (sub) experssion. So that no nodes are dumped several times
1504 we decrease the visited flag of the corresponding graph after each
1505 walk. So now increase it finally. */
1506 inc_irg_visited(get_const_code_irg());
1509 current_ir_graph = rem;
1513 dump_all_types (void)
1515 vcg_open_name ("All_types");
1516 type_walk(dump_type_info, NULL, NULL);
1517 inc_irg_visited(get_const_code_irg());
1522 dump_class_hierarchy (bool entities)
1524 vcg_open_name ("class_hierarchy");
1526 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1528 type_walk(dump_class_hierarchy_node, NULL, NULL);
1532 /***********************************************************************/
1533 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1535 /* dump_ir_block_graph */
1537 /* dump_type_graph */
1538 /* dump_ir_graph_w_types */
1539 /***********************************************************************/
1541 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1543 for (i=0; i < get_irp_n_irgs(); i++) {
1544 dmp_grph(get_irp_irg(i));