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 /* Attributes of nodes */
47 #define PRINT_DEFAULT_NODE_ATTR
48 #define DEFAULT_NODE_ATTR " "
49 #define DEFAULT_TYPE_ATTRIBUTE " "
51 /* Attributes of edges between Firm nodes */
52 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
53 #define CF_EDGE_ATTR "color: red"
54 #define MEM_EDGE_ATTR "color: blue"
55 #define DOMINATOR_EDGE_ATTR "color: red"
57 #define BACK_EDGE_ATTR "linestyle: dashed "
59 /* Attributes of edges between Firm nodes and type/entity nodes */
60 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
62 /* Attributes of edges in type/entity graphs. */
63 #define TYPE_METH_NODE_ATTR "color: lightyellow"
64 #define TYPE_CLASS_NODE_ATTR "color: green"
65 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
66 #define ENTITY_NODE_ATTR "color: yellow"
67 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
68 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
69 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
70 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
71 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
72 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
73 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
74 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
75 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
76 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
77 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
78 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
79 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
82 #if DEBUG_libfirm && NODEID_AS_LABEL
83 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
84 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
85 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
86 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
87 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
90 #define PRINT_NODEID(X) fprintf(F, "n%p", (void*) X)
91 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *) X)
92 #define PRINT_ENTID(X) fprintf(F, "e%p", (void*) X)
93 #define PRINT_IRGID(X) fprintf(F, "g%p",(void*) X)
94 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*) X, (void*) Y)
97 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
102 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
103 fprintf(F, " targetname: "); PRINT_TYPEID(T);
104 vfprintf(F, fmt, ap);
109 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
114 fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
115 fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
116 vfprintf(F, fmt, ap);
121 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, const char *fmt, ...)
126 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
127 fprintf(F, "\" targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");
128 vfprintf(F, fmt, ap);
133 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
138 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
139 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
140 vfprintf(F, fmt, ap);
145 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
150 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
151 fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
152 vfprintf(F, fmt, ap);
157 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
162 fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
163 fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
165 vfprintf(F, fmt, ap);
170 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
175 fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
176 fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
177 vfprintf(F, fmt, ap);
182 /*******************************************************************/
183 /* global and ahead declarations */
184 /*******************************************************************/
186 /* A suffix to manipulate the file name. */
187 char *dump_file_suffix = NULL;
189 /* file to dump to */
192 static void dump_whole_node(ir_node *n, void* env);
193 static INLINE void dump_loop_info(ir_graph *irg);
195 /*******************************************************************/
196 /* Helper functions. */
197 /*******************************************************************/
199 /* Use private link attr to be able to call dumper anywhere without
200 destroying link fields. */
202 static pmap *irdump_link_map = NULL;
204 static void init_irdump(void) {
205 /* We need a new, empty map. */
206 if (irdump_link_map) pmap_destroy(irdump_link_map);
207 irdump_link_map = pmap_create();
211 void *ird_get_irn_link(ir_node *n) {
213 if (!irdump_link_map) return NULL;
215 if (pmap_contains(irdump_link_map, (void *)n))
216 res = pmap_get(irdump_link_map, (void *)n);
220 void ird_set_irn_link(ir_node *n, void *x) {
221 if (!irdump_link_map) init_irdump();
222 pmap_insert(irdump_link_map, (void *)n, x);
225 void *ird_get_irg_link(ir_graph *irg) {
227 if (!irdump_link_map) return NULL;
229 if (pmap_contains(irdump_link_map, (void *)irg))
230 res = pmap_get(irdump_link_map, (void *)irg);
234 void ird_set_irg_link(ir_graph *irg, void *x) {
235 if (!irdump_link_map) init_irdump();
236 pmap_insert(irdump_link_map, (void *)irg, x);
239 static void clear_link(ir_node * node, void * env) {
240 ird_set_irn_link(node, NULL);
244 static int node_floats(ir_node *n) {
245 return ((get_op_pinned(get_irn_op(n)) == floats) &&
246 (get_irg_pinned(current_ir_graph) == floats));
249 static ident *get_irg_dump_name (ir_graph *irg) {
250 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
251 entity *ent = get_irg_ent(irg);
252 if (ent->ld_name) return ent->ld_name;
256 static void collect_node(ir_node * node, void *env) {
259 || get_irn_op(node) == op_Bad
260 || get_irn_op(node) == op_Unknown) {
261 ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
262 if (!arr) arr = NEW_ARR_F(ir_node *, 0);
263 ARR_APP1(ir_node *, arr, node);
264 ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
266 ir_node * block = get_nodes_block(node);
267 ird_set_irn_link(node, ird_get_irn_link(block));
268 ird_set_irn_link(block, node);
272 /** Construct lists to walk ir block-wise.
274 * Collects all blocks, nodes not pinned,
275 * Bad and Unknown into a flexible array in link field of
276 * irg they belong to. Sets the irg link field to NULL in all
277 * graphs not visited.
278 * Free the list with DEL_ARR_F. */
279 static ir_node ** construct_block_lists(ir_graph *irg) {
281 ir_graph *rem = current_ir_graph;
282 current_ir_graph = irg;
284 for (i = 0; i < get_irp_n_irgs(); i++)
285 ird_set_irg_link(get_irp_irg(i), NULL);
287 irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
289 current_ir_graph = rem;
290 return ird_get_irg_link(irg);
293 /*******************************************************************/
294 /* flags to steer output */
295 /*******************************************************************/
297 /* A compiler option to turn off edge labels */
299 /* A compiler option to turn off dumping values of constant entities */
300 int const_entities = 1;
301 /* A compiler option to dump the keep alive edges */
302 int dump_keepalive = 0;
303 /* Compiler options to dump analysis information in dump_ir_graph */
304 int dump_out_edge_flag = 0;
305 int dump_dominator_information_flag = 0;
306 int dump_loop_information_flag = 0;
307 int dump_backedge_information_flag = 1;
308 int dump_const_local = 0;
309 bool opt_dump_analysed_type_info = 1;
310 bool opt_dump_pointer_values_to_info = 0; /* default off: for test compares!! */
312 INLINE bool get_opt_dump_const_local(void) {
313 if (!dump_out_edge_flag && !dump_loop_information_flag)
314 return dump_const_local;
319 /* To turn off display of edge labels. Edge labels offen cause xvcg to
320 abort with a segmentation fault. */
321 void turn_off_edge_labels(void) {
325 void dump_consts_local(bool b) {
326 dump_const_local = b;
329 void turn_off_constant_entity_values(void) {
333 void dump_keepalive_edges(bool b) {
337 bool get_opt_dump_keepalive_edges(void) {
338 return dump_keepalive;
341 void dump_out_edges(void) {
342 dump_out_edge_flag = 1;
345 void dump_dominator_information(void) {
346 dump_dominator_information_flag = 1;
349 void dump_loop_information(void) {
350 dump_loop_information_flag = 1;
353 void dont_dump_loop_information(void) {
354 dump_loop_information_flag = 0;
357 void dump_backedge_information(bool b) {
358 dump_backedge_information_flag = b;
361 /* Dump the information of type field specified in ana/irtypeinfo.h.
362 * If the flag is set, the type name is output in [] in the node label,
363 * else it is output as info.
365 void dump_analysed_type_info(bool b) {
366 opt_dump_analysed_type_info = b;
369 void dump_pointer_values_to_info(bool b) {
370 opt_dump_pointer_values_to_info = b;
373 /*******************************************************************/
374 /* Routines to dump information about a single ir node. */
375 /*******************************************************************/
378 dump_node_opcode (ir_node *n)
381 switch(get_irn_opcode(n)) {
386 res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
387 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
392 if (get_SymConst_kind(n) == linkage_ptr_info) {
393 /* don't use get_SymConst_ptr_info as it mangles the name. */
394 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
396 assert(get_kind(get_SymConst_type(n)) == k_type);
397 assert(get_type_ident(get_SymConst_type(n)));
398 fprintf (F, "SymC %s ", get_type_name(get_SymConst_type(n)));
399 if (get_SymConst_kind(n) == type_tag)
407 if (!interprocedural_view) fprintf(F, "Proj'");
408 else fprintf(F, "%s", get_irn_opname(n));
412 if (interprocedural_view) {
413 fprintf(F, "%s %s", get_irn_opname(n), get_entity_name(get_irg_ent(get_irn_irg(n))));
419 fprintf (F, "%s", get_irn_opname(n));
426 dump_node_mode (ir_node *n)
428 switch (get_irn_opcode(n)) {
447 fprintf (F, "%s", get_mode_name(get_irn_mode(n)));
454 static void dump_node_typeinfo(ir_node *n) {
455 if (!opt_dump_analysed_type_info) return;
456 if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent ||
457 get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent ) {
458 type *tp = get_irn_type(n);
460 fprintf (F, " [%s]", get_type_name(tp));
467 dump_node_nodeattr (ir_node *n)
469 switch (get_irn_opcode(n)) {
471 if (false && interprocedural_view) {
472 fprintf (F, "%s", get_entity_name(get_irg_ent(current_ir_graph)));
476 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
477 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
479 fprintf (F, "%ld", get_Proj_proj(n));
483 fprintf (F, "%ld", get_Filter_proj(n));
486 fprintf (F, "%s", get_entity_name(get_Sel_entity(n)));
489 fprintf (F, "(%s)", get_type_name(get_Cast_type(n)));
492 fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
501 dump_node_vcgattr (ir_node *n)
503 switch (get_irn_opcode(n)) {
510 fprintf (F, "color: blue");
513 fprintf (F, "color: lightyellow");
516 fprintf (F, "color: green");
522 fprintf (F, "color: yellow");
525 PRINT_DEFAULT_NODE_ATTR;
530 dump_node_info (ir_node *n) {
532 fprintf (F, " info1: \"");
533 if (opt_dump_pointer_values_to_info)
534 fprintf (F, "addr: %p \n", (void *)n);
535 fprintf (F, "visited: %ld \n", get_irn_visited(n));
538 switch(get_irn_opcode(n)) {
540 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
541 fprintf(F, "start of method of type %s \n", get_type_name(tp));
542 for (i = 0; i < get_method_n_params(tp); ++i)
543 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
546 fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
549 fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
552 fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
553 fprintf(F, " from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
556 type *tp = get_Call_type(n);
557 fprintf(F, "calling method of type %s \n", get_type_name(tp));
558 for (i = 0; i < get_method_n_params(tp); ++i)
559 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
560 for (i = 0; i < get_method_n_ress(tp); ++i)
561 fprintf(F, " resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
564 if (!interprocedural_view) {
565 type *tp = get_entity_type(get_irg_ent(get_irn_irg(n)));
566 fprintf(F, "return in method of type %s \n", get_type_name(tp));
567 for (i = 0; i < get_method_n_ress(tp); ++i)
568 fprintf(F, " res %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
572 type *tp = get_Const_type(n);
573 assert(tp != none_type);
574 fprintf(F, "Const of type %s \n", get_type_name(get_Const_type(n)));
579 if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent ||
580 get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent )
581 if (get_irn_type(n) != none_type)
582 fprintf (F, "\nAnalysed type: %s", get_type_name(get_irn_type(n)));
587 /* Returns true if n and pred pos are in different graphs. */
588 static bool pred_in_wrong_graph(ir_node *n, int pos) {
589 ir_node *pred = get_irn_n(n, pos);
591 if (get_irn_irg(n) != get_irn_irg(pred)) return true;
597 bool is_constlike_node(ir_node *n) {
598 ir_op *op = get_irn_op(n);
599 return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
603 /* outputs the predecessors of n, that are constants, local. I.e.,
604 generates a copy of the constant for each node called with. */
605 static void dump_const_node_local(ir_node *n) {
607 if (!get_opt_dump_const_local()) return;
608 /* Use visited flag to avoid outputting nodes twice.
609 initialize it first. */
610 for (i = 0; i < get_irn_arity(n); i++) {
611 ir_node *con = get_irn_n(n, i);
612 if (is_constlike_node(con)) {
613 if (pred_in_wrong_graph(n, i)) continue; /* pred not dumped */
614 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
617 for (i = 0; i < get_irn_arity(n); i++) {
618 ir_node *con = get_irn_n(n, i);
619 if (is_constlike_node(con) && irn_not_visited(con)) {
620 if (pred_in_wrong_graph(n, i)) continue; /* pred not dumped */
621 mark_irn_visited(con);
622 /* Generate a new name for the node by appending the names of
624 fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
625 fprintf(F, " label: \"");
626 dump_node_opcode(con);
627 dump_node_mode (con);
628 dump_node_typeinfo(con);
630 dump_node_nodeattr(con);
632 fprintf (F, " %ld", get_irn_node_nr(con));
635 dump_node_vcgattr(con);
643 dump_node (ir_node *n) {
644 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
647 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
651 dump_node_typeinfo(n);
653 dump_node_nodeattr(n);
655 fprintf (F, " %ld", get_irn_node_nr(n));
658 dump_node_vcgattr(n);
661 dump_const_node_local(n);
664 /* dump the edge to the block this node belongs to */
666 dump_ir_block_edge(ir_node *n) {
667 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
668 if (is_no_Block(n)) {
669 fprintf (F, "edge: { sourcename: \"");
671 fprintf (F, "\" targetname: \"");
672 PRINT_NODEID(get_nodes_block(n));
673 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
677 static void print_edge_vcgattr(ir_node *from, int to) {
680 if (dump_backedge_information_flag && is_backedge(from, to))
681 fprintf (F, BACK_EDGE_ATTR);
683 switch (get_irn_opcode(from)) {
685 fprintf (F, CF_EDGE_ATTR);
687 case iro_Start: break;
690 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
691 fprintf (F, CF_EDGE_ATTR);
692 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
693 fprintf (F, MEM_EDGE_ATTR);
696 case iro_EndReg: break;
697 case iro_EndExcept: break;
699 case iro_Break: break;
700 case iro_Cond: break;
703 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
705 case iro_Const: break;
706 case iro_SymConst:break;
709 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
711 case iro_CallBegin: break;
714 case iro_Minus: break;
720 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
728 case iro_Shrs: break;
731 case iro_Conv: break;
733 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
739 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
742 fprintf (F, MEM_EDGE_ATTR);
744 case iro_Tuple: break;
747 switch (get_irn_modecode(from)) {
749 fprintf (F, CF_EDGE_ATTR);
752 fprintf (F, MEM_EDGE_ATTR);
758 case iro_Unknown: break;
765 /* dump edges to our inputs */
767 dump_ir_data_edges(ir_node *n) {
768 int i, visited = get_irn_visited(n);
770 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
773 for (i = 0; i < get_irn_arity(n); i++) {
774 ir_node * pred = get_irn_n(n, i);
776 if ((interprocedural_view && get_irn_visited(pred) < visited))
777 continue; /* pred not dumped */
778 if (dump_backedge_information_flag && is_backedge(n, i))
779 fprintf (F, "backedge: {sourcename: \"");
781 fprintf (F, "edge: {sourcename: \"");
783 fprintf (F, "\" targetname: ");
784 if ((get_opt_dump_const_local()) && is_constlike_node(pred) &&
785 !pred_in_wrong_graph(n, i)) {
786 PRINT_CONSTID(n, pred);
788 fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
790 fprintf (F, " label: \"%d\" ", i);
791 print_edge_vcgattr(n, i);
796 /** Dumps a node and its edges but not the block edge
799 dump_node_wo_blockedge (ir_node *n, void* env) {
801 dump_ir_data_edges(n);
804 /** Dumps a node and its edges.
807 dump_whole_node (ir_node *n, void* env) {
808 dump_node_wo_blockedge(n, env);
809 if (!node_floats(n)) dump_ir_block_edge(n);
813 dump_const_node(ir_node *n, void *env) {
814 if (is_Block(n)) return;
815 dump_node_wo_blockedge(n, env);
818 /***********************************************************************/
819 /* the following routines dump the nodes/irgs bracketed to graphs. */
820 /***********************************************************************/
822 /** Dumps a constant expression as entity initializer, array bound ...
824 static void dump_const_expression(ir_node *value) {
825 ir_graph *rem = current_ir_graph;
826 int rem_dump_const_local = dump_const_local;
827 dump_const_local = 0;
828 current_ir_graph = get_const_code_irg();
829 irg_walk(value, dump_const_node, NULL, NULL);
830 /* Decrease visited flag so that we walk with the same flag for the next
831 expresssion. This guarantees that we don't dump the same node twice,
832 as for const expressions cse is performed to save memory. */
833 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
834 current_ir_graph = rem;
835 dump_const_local = rem_dump_const_local;
838 /** Dump a block as graph containing its nodes.
840 * Expects to find nodes belonging to the block as list in its
842 * Dumps the edges of all nodes including itself. */
844 dump_whole_block(ir_node *block) {
846 assert(is_Block(block));
848 fprintf(F, "graph: { title: \"");
850 fprintf(F, "\" label: \"");
851 dump_node_opcode(block);
852 fprintf (F, " %ld", get_irn_node_nr(block));
854 fprintf(F, "\" status:clustered color:%s \n",
855 get_Block_matured(block) ? "yellow" : "red");
857 /* dump the blocks edges */
858 dump_ir_data_edges(block);
860 /* dump the nodes that go into the block */
861 for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
863 dump_ir_data_edges(node);
866 /* Close the vcg information for the block */
868 dump_const_node_local(block);
872 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
873 * The outermost nodes: blocks and nodes not pinned, Bad, Unknown. */
875 dump_block_graph (ir_graph *irg) {
877 ir_graph *rem = current_ir_graph;
878 ir_node **arr = ird_get_irg_link(irg);
879 current_ir_graph = irg;
881 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
882 ir_node * node = arr[i];
883 if (is_Block(node)) {
884 /* Dumps the block and all the nodes in the block, which are to
885 be found in Block->link. */
886 dump_whole_block(node);
888 /* Nodes that are not in a Block. */
890 dump_ir_data_edges(node);
894 if (dump_loop_information_flag) dump_loop_info(irg);
896 current_ir_graph = rem;
899 /** Dumps an irg as a graph.
900 * If interprocedural view edges can point to nodes out of this graph.
902 static void dump_graph(ir_graph *irg) {
904 fprintf(F, "graph: { title: \"");
906 fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
907 get_entity_name(get_irg_ent(irg)));
909 dump_block_graph (irg);
911 /* Close the vcg information for the irg */
915 /*******************************************************************/
916 /* Basic type and entity nodes and edges. */
917 /*******************************************************************/
919 /* dumps the edges between nodes and their type or entity attributes. */
920 static void dump_node2type_edges (ir_node *n, void *env)
924 switch (get_irn_opcode(n)) {
926 /* @@@ some consts have an entity */
929 if ( (get_SymConst_kind(n) == type_tag)
930 || (get_SymConst_kind(n) == size))
932 print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
936 print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
939 print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
942 print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
945 print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
948 print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
956 static void print_type_info(type *tp) {
957 if (get_type_state(tp) == layout_undefined) {
958 fprintf(F, "state: layout_undefined\n");
960 fprintf(F, "state: layout_fixed,\n");
962 if (get_type_mode(tp))
963 fprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
964 fprintf(F, "size: %dB,\n", get_type_size(tp));
967 static void print_typespecific_info(type *tp) {
968 switch (get_type_tpop_code(tp)) {
971 fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
985 case tpo_enumeration:
999 static void print_typespecific_vcgattr(type *tp) {
1000 switch (get_type_tpop_code(tp)) {
1003 if (peculiarity_existent == get_class_peculiarity(tp))
1004 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1006 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1010 fprintf (F, " " TYPE_METH_NODE_ATTR);
1021 case tpo_enumeration:
1034 static void print_type_node(type *tp)
1036 fprintf (F, "node: {title: ");
1038 fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name(tp));
1039 fprintf (F, " info1: \"");
1040 print_type_info(tp);
1041 print_typespecific_info(tp);
1043 print_typespecific_vcgattr(tp);
1047 #define X(a) case a: fprintf(F, #a); break
1048 void dump_entity_node(entity *ent)
1050 fprintf (F, "node: {title: \"");
1051 PRINT_ENTID(ent); fprintf(F, "\"");
1052 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1053 fprintf (F, "label: ");
1054 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_entity_name(ent));
1055 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
1057 fprintf (F, "\nallocation: ");
1058 switch (get_entity_allocation(ent)) {
1059 X(allocation_dynamic);
1060 X(allocation_automatic);
1061 X(allocation_static);
1062 X(allocation_parameter);
1065 fprintf (F, "\nvisibility: ");
1066 switch (get_entity_visibility(ent)) {
1067 X(visibility_local);
1068 X(visibility_external_visible);
1069 X(visibility_external_allocated);
1072 fprintf (F, "\nvariability: ");
1073 switch (get_entity_variability(ent)) {
1074 X(variability_uninitialized);
1075 X(variability_initialized);
1076 X(variability_part_constant);
1077 X(variability_constant);
1080 fprintf (F, "\nvolatility: ");
1081 switch (get_entity_volatility(ent)) {
1082 X(volatility_non_volatile);
1083 X(volatility_is_volatile);
1086 fprintf(F, "\npeculiarity: %s", get_peculiarity_string(get_entity_peculiarity(ent)));
1087 fprintf(F, "\nname: %s\nld_name: %s",
1088 get_entity_name(ent), ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
1089 fprintf(F, "\noffset: %d", get_entity_offset(ent));
1090 if (is_method_type(get_entity_type(ent))) {
1091 if (get_entity_irg(ent)) /* can be null */
1092 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
1094 { fprintf (F, "\nirg = NULL"); }
1096 fprintf(F, "\"\n}\n");
1100 /* dumps a type or entity and it's edges. */
1102 dump_type_info (type_or_ent *tore, void *env) {
1103 int i = 0; /* to shutup gcc */
1105 /* dump this type or entity */
1107 switch (get_kind(tore)) {
1110 entity *ent = (entity *)tore;
1113 dump_entity_node(ent);
1115 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
1116 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1117 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1118 print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1119 if(is_class_type(get_entity_owner(ent))) {
1120 for(i = 0; i < get_entity_n_overwrites(ent); i++){
1121 print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
1124 /* attached subgraphs */
1125 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1126 if (is_atomic_entity(ent)) {
1127 value = get_atomic_ent_value(ent);
1129 print_ent_node_edge(F,ent, value, ENT_VALUE_EDGE_ATTR, i);
1130 /* DDMN(value); $$$ */
1131 dump_const_expression(value);
1134 if (is_compound_entity(ent)) {
1135 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1136 value = get_compound_ent_value(ent, i);
1138 print_ent_node_edge(F,ent,value,ENT_VALUE_EDGE_ATTR,i);
1139 dump_const_expression(value);
1140 print_ent_ent_edge(F,ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
1142 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1143 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
1144 get_compound_ent_value_member(ent, i), i);
1153 type *tp = (type *)tore;
1154 print_type_node(tp);
1155 /* and now the edges */
1156 switch (get_type_tpop_code(tp)) {
1159 for (i=0; i < get_class_n_supertypes(tp); i++) {
1160 print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1163 for (i=0; i < get_class_n_members(tp); i++) {
1164 print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1169 for (i=0; i < get_struct_n_members(tp); i++) {
1170 print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1175 for (i = 0; i < get_method_n_params(tp); i++)
1177 print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1179 for (i = 0; i < get_method_n_ress(tp); i++)
1181 print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1186 for (i = 0; i < get_union_n_members(tp); i++)
1188 print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1193 print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1194 print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1195 for (i = 0; i < get_array_n_dimensions(tp); i++) {
1196 ir_node *upper = get_array_upper_bound(tp, i);
1197 ir_node *lower = get_array_lower_bound(tp, i);
1198 print_node_type_edge(F,upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1199 print_node_type_edge(F,lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1200 dump_const_expression(upper);
1201 dump_const_expression(lower);
1205 case tpo_enumeration:
1210 print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1218 break; /* case k_type */
1221 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
1223 } /* switch kind_or_entity */
1226 /** For dumping class hierarchies.
1227 * Dumps a class type node and a superclass edge.
1228 * If env != null dumps entities of classes and overwrites edges.
1231 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
1232 int i = 0; /* to shutup gcc */
1234 /* dump this type or entity */
1235 switch (get_kind(tore)) {
1237 entity *ent = (entity *)tore;
1238 if (get_entity_owner(ent) == get_glob_type()) break;
1239 if ((env) && is_class_type(get_entity_owner(ent))) {
1241 dump_entity_node(ent);
1243 print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1244 for(i = 0; i < get_entity_n_overwrites(ent); i++)
1246 print_ent_ent_edge(F,get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
1249 } break; /* case k_entity */
1252 type *tp = (type *)tore;
1253 if (tp == get_glob_type()) break;
1254 switch (get_type_tpop_code(tp)) {
1256 print_type_node(tp);
1257 /* and now the edges */
1258 for (i=0; i < get_class_n_supertypes(tp); i++)
1260 print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1266 break; /* case k_type */
1269 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1271 } /* switch kind_or_entity */
1274 /*******************************************************************/
1275 /* dump analysis information that is expressed in graph terms. */
1276 /*******************************************************************/
1278 /* dump out edges */
1280 dump_out_edge (ir_node *n, void* env) {
1282 for (i = 0; i < get_irn_n_outs(n); i++) {
1283 assert(get_irn_out(n, i));
1284 fprintf (F, "edge: {sourcename: \"");
1286 fprintf (F, "\" targetname: \"");
1287 PRINT_NODEID(get_irn_out(n, i));
1288 fprintf (F, "\" color: red linestyle: dashed");
1294 dump_loop_node_edge (ir_loop *loop, int i) {
1296 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
1297 PRINT_NODEID(get_loop_node(loop, i));
1298 fprintf (F, "\" color: green");
1303 dump_loop_son_edge (ir_loop *loop, int i) {
1305 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\" color: darkgreen}\n",
1306 (void *)loop, (void *)get_loop_son(loop, i));
1310 void dump_loops (ir_loop *loop) {
1312 /* dump this loop node */
1313 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
1314 (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1315 /* dump edges to nodes in loop -- only if it is a real loop */
1316 if (get_loop_depth(loop) != 0) {
1317 for (i = 0; i < get_loop_n_nodes(loop); i++) {
1318 dump_loop_node_edge(loop, i);
1321 for (i = 0; i < get_loop_n_sons(loop); i++) {
1322 dump_loops(get_loop_son(loop, i));
1323 dump_loop_son_edge(loop, i);
1328 void dump_loop_info(ir_graph *irg) {
1329 ir_graph *rem = current_ir_graph;
1330 current_ir_graph = irg;
1332 if (get_irg_loop(irg)) dump_loops(get_irg_loop(irg));
1334 current_ir_graph = rem;
1338 /************************************************************************/
1339 /* open and close vcg file */
1340 /************************************************************************/
1343 dump_vcg_header(const char *name) {
1353 "graph: { title: \"ir graph of %s\"\n"
1354 "display_edge_labels: %s\n"
1355 "layoutalgorithm: mindepth\n"
1356 "manhattan_edges: yes\n"
1357 "port_sharing: no\n"
1358 "orientation: bottom_to_top\n"
1359 "classname 1: \"Data\"\n"
1360 "classname 2: \"Block\"\n"
1361 "classname 3: \"Entity type\"\n"
1362 "classname 4: \"Entity owner\"\n"
1363 "classname 5: \"Method Param\"\n"
1364 "classname 6: \"Method Res\"\n"
1365 "classname 7: \"Super\"\n"
1366 "classname 8: \"Union\"\n"
1367 "classname 9: \"Points-to\"\n"
1368 "classname 10: \"Array Element Type\"\n"
1369 "classname 11: \"Overwrites\"\n"
1370 "classname 12: \"Member\"\n",
1373 fprintf (F, "\n"); /* a separator */
1376 static void vcg_open (ir_graph *irg, char *suffix) {
1377 char *fname; /* filename to put the vcg information in */
1382 /** open file for vcg graph */
1383 id = get_irg_dump_name(irg);
1384 len = get_id_strlen (id);
1385 cp = get_id_str (id);
1386 if (dump_file_suffix)
1387 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
1389 fname = malloc (len + 5 + strlen(suffix));
1390 strncpy (fname, cp, len); /* copy the filename */
1392 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
1393 strcat (fname, suffix); /* append file suffix */
1394 strcat (fname, ".vcg"); /* append the .vcg suffix */
1395 F = fopen (fname, "w"); /* open file for writing */
1397 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1399 dump_vcg_header(cp);
1402 static void vcg_open_name (const char *name) {
1403 char *fname; /* filename to put the vcg information in */
1406 /** open file for vcg graph */
1408 fname = malloc (len + 5);
1409 if (dump_file_suffix)
1410 fname = malloc (len + 5 + strlen(dump_file_suffix));
1412 fname = malloc (len + 5);
1413 strcpy (fname, name); /* copy the filename */
1414 if (dump_file_suffix) strcat (fname, dump_file_suffix);
1415 strcat (fname, ".vcg"); /* append the .vcg suffix */
1416 F = fopen (fname, "w"); /* open file for writing */
1418 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1421 dump_vcg_header(name);
1426 fprintf (F, "}\n"); /* print footer */
1427 fclose (F); /* close vcg file */
1430 /************************************************************************/
1431 /************************************************************************/
1432 /* Routines that dump all or parts of the firm representation to a file */
1433 /************************************************************************/
1434 /************************************************************************/
1436 /************************************************************************/
1437 /* Dump ir graphs, differnt formats and additional information. */
1438 /************************************************************************/
1440 /** Routine to dump a graph, blocks as conventional nodes.
1443 dump_ir_graph (ir_graph *irg)
1447 rem = current_ir_graph;
1448 current_ir_graph = irg;
1450 if (interprocedural_view) suffix = "-pure-ip";
1451 else suffix = "-pure";
1452 vcg_open (irg, suffix);
1454 /* walk over the graph */
1455 /* dump_whole_node must be called in post visiting predecessors */
1456 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1458 /* dump the out edges in a separate walk */
1459 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1460 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1465 current_ir_graph = rem;
1470 dump_ir_block_graph (ir_graph *irg)
1475 construct_block_lists(irg);
1477 if (interprocedural_view) suffix = "-ip";
1479 vcg_open (irg, suffix);
1481 for (i = 0; i < get_irp_n_irgs(); i++) {
1482 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1484 dump_graph(get_irp_irg(i));
1492 /** dumps a graph with type information
1495 dump_ir_graph_w_types (ir_graph *irg)
1497 ir_graph *rem = current_ir_graph;
1499 current_ir_graph = irg;
1501 if (interprocedural_view) suffix = "-pure-wtypes-ip";
1502 else suffix = "-pure-wtypes";
1503 vcg_open (irg, suffix);
1505 /* dump common ir graph */
1506 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1507 /* dump type info */
1508 type_walk_irg(irg, dump_type_info, NULL, NULL);
1509 inc_irg_visited(get_const_code_irg());
1510 /* dump edges from graph to type info */
1511 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1514 current_ir_graph = rem;
1518 dump_ir_block_graph_w_types (ir_graph *irg)
1522 ir_graph *rem = current_ir_graph;
1524 if (interprocedural_view) suffix = "-wtypes-ip";
1525 else suffix = "-wtypes";
1526 vcg_open (irg, suffix);
1528 /* dump common blocked ir graph */
1529 construct_block_lists(irg);
1531 for (i = 0; i < get_irp_n_irgs(); i++) {
1532 ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1534 dump_graph(get_irp_irg(i));
1539 /* dump type info */
1540 current_ir_graph = irg;
1541 type_walk_irg(irg, dump_type_info, NULL, NULL);
1542 inc_irg_visited(get_const_code_irg());
1544 /* dump edges from graph to type info */
1545 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1547 current_ir_graph = rem;
1551 /***********************************************************************/
1552 /* The following routines dump a control flow graph. */
1553 /***********************************************************************/
1556 dump_block_to_cfg (ir_node *block, void *env) {
1560 if (is_Block(block)) {
1561 /* This is a block. Dump a node for the block. */
1562 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1563 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1564 PRINT_NODEID(block);
1566 if (dump_dominator_information_flag)
1567 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1569 /* Dump the edges */
1570 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1571 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1572 pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1573 fprintf (F, "edge: { sourcename: \"");
1574 PRINT_NODEID(block);
1575 fprintf (F, "\" targetname: \"");
1577 fprintf (F, "\"}\n");
1580 /* Dump dominator edge */
1581 if (dump_dominator_information_flag && get_Block_idom(block)) {
1582 pred = get_Block_idom(block);
1583 fprintf (F, "edge: { sourcename: \"");
1584 PRINT_NODEID(block);
1585 fprintf (F, "\" targetname: \"");
1587 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1593 dump_cfg (ir_graph *irg)
1595 ir_graph *rem = current_ir_graph;
1596 int ddif = dump_dominator_information_flag;
1597 int ipv = interprocedural_view;
1598 current_ir_graph = irg;
1599 vcg_open (irg, "-cfg");
1601 if (interprocedural_view) {
1602 printf("Warning: dumping cfg not in interprocedural view!\n");
1603 interprocedural_view = 0;
1606 if (get_irg_dom_state(irg) != dom_consistent)
1607 dump_dominator_information_flag = 0;
1609 /* walk over the blocks in the graph */
1610 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1611 dump_node (get_irg_bad(irg));
1613 dump_dominator_information_flag = ddif;
1614 interprocedural_view = ipv;
1616 current_ir_graph = rem;
1621 /* Dump all irgs in interprocedural view to a single file. */
1622 void dump_all_cg_block_graph(void) {
1624 int rem_view = interprocedural_view;
1625 interprocedural_view = 1;
1626 vcg_open_name ("All_graphs");
1628 /* collect nodes in all irgs reachable in call graph*/
1629 for (i = 0; i < get_irp_n_irgs(); i++)
1630 ird_set_irg_link(get_irp_irg(i), NULL);
1632 cg_walk(clear_link, collect_node, NULL);
1634 /* dump all graphs */
1635 for (i = 0; i < get_irp_n_irgs(); i++) {
1636 current_ir_graph = get_irp_irg(i);
1637 dump_graph(current_ir_graph);
1638 DEL_ARR_F(ird_get_irg_link(current_ir_graph));
1642 interprocedural_view = rem_view;
1645 /***********************************************************************/
1646 /* the following routines dumps type information without any ir nodes. */
1647 /***********************************************************************/
1650 dump_type_graph (ir_graph *irg)
1653 rem = current_ir_graph;
1654 current_ir_graph = irg;
1656 vcg_open (irg, "-type");
1658 /* walk over the blocks in the graph */
1659 type_walk_irg(irg, dump_type_info, NULL, NULL);
1660 /* The walker for the const code can be called several times for the
1661 same (sub) experssion. So that no nodes are dumped several times
1662 we decrease the visited flag of the corresponding graph after each
1663 walk. So now increase it finally. */
1664 inc_irg_visited(get_const_code_irg());
1667 current_ir_graph = rem;
1671 dump_all_types (void)
1673 vcg_open_name ("All_types");
1674 type_walk(dump_type_info, NULL, NULL);
1675 inc_irg_visited(get_const_code_irg());
1680 dump_class_hierarchy (bool entities)
1682 vcg_open_name ("class_hierarchy");
1684 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1686 type_walk(dump_class_hierarchy_node, NULL, NULL);
1690 /***********************************************************************/
1691 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1693 /* dump_ir_block_graph */
1695 /* dump_type_graph */
1696 /* dump_ir_graph_w_types */
1697 /***********************************************************************/
1699 void dump_all_ir_graphs (dump_graph_func *dmp_grph) {
1701 for (i=0; i < get_irp_n_irgs(); i++) {
1702 dmp_grph(get_irp_irg(i));