1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 ** All rights reserved.
4 ** Authors: Martin Trapp, Christian Schaefer
6 ** irdump.h: dumping of an intermediate representation graph
15 # include "irnode_t.h"
16 # include "irgraph_t.h"
21 # include "entity_t.h"
26 # include "type_or_entity.h"
28 # include "typewalk.h"
31 # include "common_t.h"
38 /* Attributes of nodes */
39 #define DEFAULT_NODE_ATTR ""
40 #define DEFAULT_TYPE_ATTRIBUTE ""
42 /* Attributes of edges between Firm nodes */
43 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
44 #define CF_EDGE_ATTR "color: red"
45 #define MEM_EDGE_ATTR "color: blue"
46 #define DOMINATOR_EDGE_ATTR "color: red"
48 #define BACK_EDGE_ATTR "linestyle: dashed "
50 /* Attributes of edges between Firm nodes and type/entity nodes */
51 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
53 /* Attributes of edges in type/entity graphs. */
54 #define TYPE_METH_NODE_ATTR "color: lightyellow"
55 #define TYPE_CLASS_NODE_ATTR "color: green"
56 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
57 #define ENTITY_NODE_ATTR "color: yellow"
58 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
59 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
60 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
61 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
62 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: blue"
63 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
64 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
65 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
66 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
67 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
68 #define ENT_VALUE_EDGE_ATTR "label: \"value "
69 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
70 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
73 #if DEBUG_libfirm && NODEID_AS_LABEL
74 #define PRINT_NODEID(X) fprintf(F, "%ld", get_irn_node_nr(X))
76 #define PRINT_NODEID(X) fprintf(F, "%p", X)
79 /* A suffix to manipulate the file name. */
80 char *dump_file_suffix = NULL;
85 /* A compiler option to turn off edge labels */
87 /* A compiler option to turn off dumping values of constant entities */
88 int const_entities = 1;
89 /* A compiler option to dump the keep alive edges */
90 int dump_keepalive = 0;
91 /* Compiler options to dump analysis information in dump_ir_graph */
92 int dump_out_edge_flag = 0;
93 int dump_dominator_information_flag = 0;
94 int dump_loop_information_flag = 0;
95 int dump_const_local = 0;
96 static INLINE bool dump_const_local_set() {
97 if (!dump_out_edge_flag && !dump_loop_information_flag)
98 return dump_const_local;
103 /* A global variable to record output of the Bad node. */
106 void dump_ir_blocks_nodes (ir_node *n, void *env);
107 void dump_whole_node (ir_node *n, void* env);
109 /*******************************************************************/
110 /* routines to dump information about a single node */
111 /*******************************************************************/
116 dump_node_opcode (ir_node *n)
121 if (n->op->code == iro_Const) {
122 xfprintf (F, "%v", n->attr.con);
125 } else if (n->op->code == iro_SymConst) {
126 if (get_SymConst_kind(n) == linkage_ptr_info) {
127 /* don't use get_SymConst_ptr_info as it mangles the name. */
128 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
130 assert(get_kind(get_SymConst_type(n)) == k_type);
131 assert(get_type_ident(get_SymConst_type(n)));
132 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
133 if (get_SymConst_kind == type_tag)
136 xfprintf (F, "size");
140 } else if (n->op->code == iro_Filter && !interprocedural_view) {
145 xfprintf (F, "%I", get_irn_opident(n));
150 dump_node_mode (ir_node *n)
152 switch (n->op->code) {
170 xfprintf (F, "%I", get_mode_ident(n->mode));
176 void dump_node_loop_info(ir_node *n) {
177 // if (get_irn_loop(n))
178 // xfprintf(F, "\n in loop %d", get_loop_depth(get_irn_loop(n)));
182 dump_node_nodeattr (ir_node *n)
184 switch (n->op->code) {
186 if (false && interprocedural_view) {
187 xfprintf (F, "%I", get_entity_ident(get_irg_ent(current_ir_graph)));
191 if (n->in[1]->op->code == iro_Cmp) {
192 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
194 xfprintf (F, "%ld", n->attr.proj);
198 xfprintf (F, "%ld", n->attr.filter.proj);
201 assert(get_kind(get_Sel_entity(n)) == k_entity);
202 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
209 dump_node_vcgattr (ir_node *n)
211 switch (n->op->code) {
218 xfprintf (F, "color: blue");
221 xfprintf (F, "color: lightyellow");
224 xfprintf (F, "color: green");
230 xfprintf (F, "color: yellow");
233 xfprintf (F, DEFAULT_NODE_ATTR);
237 bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
238 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
241 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
242 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
243 if (is_ip_cfop(pred)) {
244 ir_graph *irg = get_ip_cfop_irg(pred);
245 if (pmap_find(irgmap, irg) == NULL) return true;
254 bool is_constlike_node(ir_node *n) {
255 ir_op *op = get_irn_op(n);
256 return (op == op_Const || op == op_Bad || op == op_SymConst);
260 void dump_const_node_local(ir_node *n, pmap *irgmap) {
262 if (!dump_const_local_set()) return;
263 /* Use visited flag to avoid outputting nodes twice.
264 initialize it first. */
265 for (i = 0; i < get_irn_arity(n); i++) {
266 ir_node *con = get_irn_n(n, i);
267 if (is_constlike_node(con)) {
268 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
269 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
272 for (i = 0; i < get_irn_arity(n); i++) {
273 ir_node *con = get_irn_n(n, i);
274 if (is_constlike_node(con) && irn_not_visited(con)) {
275 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
276 mark_irn_visited(con);
277 /* Generate a new name for the node by appending the names of
279 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); PRINT_NODEID(con);
280 fprintf(F, "\" label: \"");
281 dump_node_opcode(con);
282 dump_node_mode (con);
284 dump_node_nodeattr(con);
286 xfprintf (F, " %ld", get_irn_node_nr(con));
289 dump_node_vcgattr(con);
296 dump_node (ir_node *n, pmap * map) {
297 if (dump_const_local_set() && is_constlike_node(n)) return;
300 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
305 dump_node_nodeattr(n);
307 xfprintf (F, " %ld", get_irn_node_nr(n));
310 dump_node_vcgattr(n);
312 dump_const_node_local(n, map);
316 dump_ir_node (ir_node *n)
319 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
321 switch (n->op->code) { /* node label */
323 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
324 xfprintf (F, DEFAULT_NODE_ATTR);
331 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
332 xfprintf (F, DEFAULT_NODE_ATTR);
335 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
336 xfprintf (F, DEFAULT_NODE_ATTR);
339 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
340 if (get_irn_modecode(n) == irm_M)
341 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
343 xfprintf (F, DEFAULT_NODE_ATTR);
346 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
347 xfprintf (F, DEFAULT_NODE_ATTR);
350 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
351 xfprintf (F, DEFAULT_NODE_ATTR);
354 if (n->in[1]->op->code == iro_Cmp) {
355 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
356 get_pnc_string(n->attr.proj));
358 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
360 xfprintf (F, DEFAULT_NODE_ATTR);
363 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.filter.proj);
364 xfprintf (F, DEFAULT_NODE_ATTR);
367 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
368 xfprintf (F, DEFAULT_NODE_ATTR);
371 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
372 xfprintf (F, DEFAULT_NODE_ATTR);
375 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
376 xfprintf (F, DEFAULT_NODE_ATTR);
379 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
380 xfprintf (F, DEFAULT_NODE_ATTR);
383 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
384 xfprintf (F, DEFAULT_NODE_ATTR);
387 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
388 xfprintf (F, DEFAULT_NODE_ATTR);
391 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
392 xfprintf (F, DEFAULT_NODE_ATTR);
395 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
396 xfprintf (F, DEFAULT_NODE_ATTR);
399 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
400 xfprintf (F, DEFAULT_NODE_ATTR);
403 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
404 xfprintf (F, DEFAULT_NODE_ATTR);
407 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
408 xfprintf (F, DEFAULT_NODE_ATTR);
411 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
412 xfprintf (F, DEFAULT_NODE_ATTR);
415 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
416 xfprintf (F, DEFAULT_NODE_ATTR);
419 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
420 xfprintf (F, DEFAULT_NODE_ATTR);
423 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
424 xfprintf (F, DEFAULT_NODE_ATTR);
427 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
428 xfprintf (F, DEFAULT_NODE_ATTR);
431 xfprintf (F, "\"%I\"", get_irn_opident(n));
432 xfprintf (F, DEFAULT_NODE_ATTR);
435 xfprintf (F, "\"%I\"", get_irn_opident(n));
436 xfprintf (F, DEFAULT_NODE_ATTR);
439 xfprintf (F, "\"%I\"", get_irn_opident(n));
440 xfprintf (F, DEFAULT_NODE_ATTR);
443 xfprintf (F, "\"%I\"", get_irn_opident(n));
444 xfprintf (F, DEFAULT_NODE_ATTR);
447 xfprintf (F, "\"%I\"", get_irn_opident(n));
448 xfprintf (F, DEFAULT_NODE_ATTR);
451 xfprintf (F, "\"%I\"", get_irn_opident(n));
452 xfprintf (F, DEFAULT_NODE_ATTR);
455 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
456 xfprintf (F, DEFAULT_NODE_ATTR);
460 xfprintf (F, "\"%R\"", n);
461 xfprintf (F, DEFAULT_NODE_ATTR);
464 xfprintf (F, "\"%I\" ", get_irn_opident(n));
465 xfprintf (F, DEFAULT_NODE_ATTR);
468 assert(get_kind(get_Sel_entity(n)) == k_entity);
469 xfprintf (F, "\"%I ", get_irn_opident(n));
470 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
471 xfprintf (F, DEFAULT_NODE_ATTR);
474 assert(get_kind(get_SymConst_type(n)) == k_type);
475 assert(get_type_ident(get_SymConst_type(n)));
476 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
477 switch (n->attr.i.num){
479 xfprintf (F, "tag\" ");
482 xfprintf (F, "size\" ");
488 xfprintf (F, DEFAULT_NODE_ATTR);
491 xfprintf (F, "\"%I\" ", get_irn_opident(n));
492 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
495 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
496 xfprintf (F, DEFAULT_NODE_ATTR);
499 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
500 xfprintf (F, DEFAULT_NODE_ATTR);
503 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
505 xfprintf (F, "}\n"); /* footer */
509 /* dump the edge to the block this node belongs to */
511 dump_ir_block_edge(ir_node *n) {
512 if (dump_const_local_set() && is_constlike_node(n)) return;
513 if (is_no_Block(n)) {
514 xfprintf (F, "edge: { sourcename: \"");
516 xfprintf (F, "\" targetname: \"");
517 PRINT_NODEID(get_nodes_Block(n));
518 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
522 void print_edge_vcgattr(ir_node *from, int to) {
525 if (is_backedge(from, to)) xfprintf (F, BACK_EDGE_ATTR);
527 switch (get_irn_opcode(from)) {
529 xfprintf (F, CF_EDGE_ATTR);
531 case iro_Start: break;
534 if (get_irn_mode(get_End_keepalive(from, to)) == mode_R)
535 xfprintf (F, CF_EDGE_ATTR);
536 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
537 xfprintf (F, MEM_EDGE_ATTR);
540 case iro_EndReg: break;
541 case iro_EndExcept: break;
543 case iro_Break: break;
544 case iro_Cond: break;
547 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
549 case iro_Const: break;
550 case iro_SymConst:break;
553 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
555 case iro_CallBegin: break;
558 case iro_Minus: break;
564 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
572 case iro_Shrs: break;
575 case iro_Conv: break;
577 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
583 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
586 xfprintf (F, MEM_EDGE_ATTR);
588 case iro_Tuple: break;
591 switch (get_irn_modecode(from)) {
593 xfprintf (F, CF_EDGE_ATTR);
596 xfprintf (F, MEM_EDGE_ATTR);
602 case iro_Unknown: break;
608 /* dump edges to our inputs */
610 dump_ir_data_edges(ir_node *n) {
611 int i, visited = get_irn_visited(n);
613 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
616 for (i = 0; i < get_irn_arity(n); i++) {
617 ir_node * pred = get_irn_n(n, i);
619 if ((interprocedural_view && get_irn_visited(pred) < visited))
620 continue; /* pred not dumped */
621 if (is_backedge(n, i))
622 fprintf (F, "backedge: {sourcename: \"");
624 fprintf (F, "edge: {sourcename: \"");
626 fprintf (F, "\" targetname: \"");
627 if ((dump_const_local_set()) && is_constlike_node(pred))
631 fprintf (F, " label: \"%d\" ", i);
632 print_edge_vcgattr(n, i);
639 dump_out_edge (ir_node *n, void* env) {
641 for (i = 0; i < get_irn_n_outs(n); i++) {
642 assert(get_irn_out(n, i));
643 fprintf (F, "edge: {sourcename: \"");
645 fprintf (F, "\" targetname: \"");
646 PRINT_NODEID(get_irn_out(n, i));
647 fprintf (F, "\" color: red linestyle: dashed");
653 dump_loop_node_edge (ir_loop *loop, int i) {
655 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", loop);
656 PRINT_NODEID(get_loop_node(loop, i));
657 fprintf (F, "\" color: green");
662 void dump_loops (ir_loop *loop) {
664 /* dump this loop node */
665 xfprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
666 loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
667 /* dump edges to nodes in loop -- only if it is a real loop */
668 if (get_loop_depth(loop) != 0) {
669 for (i = 0; i < get_loop_n_nodes(loop); i++) {
670 dump_loop_node_edge(loop, i);
673 for (i = 0; i < get_loop_n_sons(loop); i++) {
674 dump_loops(get_loop_son(loop, i));
679 void dump_loop_info(ir_graph *irg) {
680 ir_graph *rem = current_ir_graph;
681 current_ir_graph = irg;
683 if (get_irg_loop(irg))
684 dump_loops(get_irg_loop(irg));
686 current_ir_graph = rem;
690 /* dumps the edges between nodes and their type or entity attributes. */
691 void dump_node2type_edges (ir_node *n, void *env)
695 switch (get_irn_opcode(n)) {
697 /* @@@ some consts have an entity */
700 if ( (get_SymConst_kind(n) == type_tag)
701 || (get_SymConst_kind(n) == size)) {
702 xfprintf (F, "edge: { sourcename: \"");
704 fprintf (F, "\" targetname: \"%p\" "
705 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
709 xfprintf (F, "edge: { sourcename: \"");
711 fprintf (F, "\" targetname: \"%p\" "
712 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
715 xfprintf (F, "edge: { sourcename: \"");
717 fprintf (F, "\" targetname: \"%p\" "
718 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
721 xfprintf (F, "edge: { sourcename: \"");
723 fprintf (F, "\" targetname: \"%p\" "
724 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
727 xfprintf (F, "edge: { sourcename: \"");
729 fprintf (F, "\" targetname: \"%p\" "
730 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
738 void dump_const_expression(ir_node *value) {
739 ir_graph *rem = current_ir_graph;
740 current_ir_graph = get_const_code_irg();
741 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
742 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
743 current_ir_graph = rem;
747 void print_type_info(type *tp) {
748 if (get_type_state(tp) == layout_undefined) {
749 xfprintf(F, "state: layout_undefined\n");
751 xfprintf(F, "state: layout_fixed,\n");
753 if (get_type_mode(tp))
754 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
755 xfprintf(F, "size: %dB,\n", get_type_size(tp));
759 void print_typespecific_info(type *tp) {
760 switch (get_type_tpop_code(tp)) {
763 if(existent == get_class_peculiarity(tp))
764 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
766 xfprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
770 xfprintf (F, " " TYPE_METH_NODE_ATTR);
781 case tpo_enumeration:
794 void print_type_node(type *tp) {
795 xfprintf (F, "node: {title: \"%p\" ", tp);
796 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
797 xfprintf (F, "info1: \"");
800 print_typespecific_info(tp);
804 /* dumps a type or entity and it's edges. */
806 dump_type_info (type_or_ent *tore, void *env) {
807 int i = 0; /* to shutup gcc */
809 /* dump this type or entity */
811 switch (get_kind(tore)) {
814 entity *ent = (entity *)tore;
817 xfprintf (F, "node: {title: \"%p\" ", tore);
818 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
819 xfprintf (F, "label: ");
820 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
821 switch (get_entity_allocation(ent)) {
822 case dynamic_allocated: fprintf (F, " info1:\"dynamic allocated\n"); break;
823 case automatic_allocated: fprintf (F, " info1:\"automatic allocated\n"); break;
824 case static_allocated: fprintf (F, " info1:\"static allocated\n"); break;
826 switch (get_entity_visibility(ent)) {
827 case local: fprintf (F, "local\n"); break;
828 case external_visible: fprintf (F, "external_visible\n"); break;
829 case external_allocated: fprintf (F, "external_allocate\n"); break;
831 switch (get_entity_variability(ent)) {
832 case uninitialized: fprintf (F, "uninitialized\n");break;
833 case initialized: fprintf (F, "initialized\n"); break;
834 case part_constant: fprintf (F, "part_constant\n");break;
835 case constant: fprintf (F, "constant\n"); break;
837 switch (get_entity_volatility(ent)) {
838 case non_volatile: fprintf (F, "non_volatile\n"); break;
839 case is_volatile: fprintf (F, "is_volatile\n"); break;
841 switch (get_entity_peculiarity(ent)) {
842 case description: fprintf (F, "description\n"); break;
843 case inherited: fprintf (F, "inherited\n"); break;
844 case existent: fprintf (F, "existent\n"); break;
846 if (is_method_type(get_entity_type(ent)))
847 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
848 xfprintf(F, "\"}\n");
850 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
851 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
852 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
853 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
854 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
855 if(is_class_type(get_entity_owner(ent))) {
856 for(i = 0; i < get_entity_n_overwrites(ent); i++)
857 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
858 ENT_OVERWRITES_EDGE_ATTR "}\n",
859 ent, get_entity_overwrites(ent, i));
861 /* attached subgraphs */
862 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
863 if (is_atomic_entity(ent)) {
864 value = get_atomic_ent_value(ent);
865 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
867 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
868 dump_const_expression(value);
870 if (is_compound_entity(ent)) {
871 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
872 value = get_compound_ent_value(ent, i);
873 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
875 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
876 dump_const_expression(value);
877 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
878 ENT_CORR_EDGE_ATTR "}\n", ent,
879 get_compound_ent_value_member(ent, i), i);
886 type *tp = (type *)tore;
888 /* and now the edges */
889 switch (get_type_tpop_code(tp)) {
892 for (i=0; i < get_class_n_supertypes(tp); i++)
893 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
894 TYPE_SUPER_EDGE_ATTR "}\n",
895 tp, get_class_supertype(tp, i));
896 for (i=0; i < get_class_n_members(tp); i++)
897 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
898 TYPE_MEMBER_EDGE_ATTR "}\n",
899 tp, get_class_member(tp, i));
903 for (i=0; i < get_struct_n_members(tp); i++)
904 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
905 TYPE_MEMBER_EDGE_ATTR "}\n",
906 tp, get_struct_member(tp, i));
910 for (i = 0; i < get_method_n_params(tp); i++)
911 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
912 METH_PAR_EDGE_ATTR "}\n",
913 tp, get_method_param_type(tp, i), i);
914 for (i = 0; i < get_method_n_ress(tp); i++)
915 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
916 METH_RES_EDGE_ATTR "}\n",
917 tp, get_method_res_type(tp, i), i);
921 for (i = 0; i < get_union_n_members(tp); i++)
922 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
923 "label: \"\"f" UNION_EDGE_ATTR "}\n",
924 tp, get_union_member(tp, i));
928 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
929 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
930 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
931 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
933 case tpo_enumeration:
938 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
939 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
940 get_pointer_points_to_type(tp), i);
948 break; /* case k_type */
951 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
953 } /* switch kind_or_entity */
956 /************************************************************************/
957 /* open and close vcg file */
958 /************************************************************************/
960 void vcg_open (ir_graph *irg, char *suffix) {
961 char *fname; /* filename to put the vcg information in */
968 /** open file for vcg graph */
969 ent = get_irg_ent(irg);
970 id = ent->ld_name ? ent->ld_name : ent->name;
971 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
972 len = id_to_strlen (id);
974 if (dump_file_suffix)
975 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
977 fname = malloc (len + 5 + strlen(suffix));
978 strncpy (fname, cp, len); /* copy the filename */
980 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
981 strcat (fname, suffix); /* append file suffix */
982 strcat (fname, ".vcg"); /* append the .vcg suffix */
983 F = fopen (fname, "w"); /* open file for writing */
985 panic ("cannot open %s for writing (%m)", fname); /* not reached */
989 strcpy(label, "yes");
991 strcpy (label, "no");
996 "graph: { title: \"ir graph of %s\"\n"
997 "display_edge_labels: %s\n"
998 "layoutalgorithm: mindepth\n"
999 "manhattan_edges: yes\n"
1000 "port_sharing: no\n"
1001 "orientation: bottom_to_top\n"
1002 "classname 1: \"Data\"\n"
1003 "classname 2: \"Block\"\n"
1004 "classname 3: \"Entity type\""
1005 "classname 4: \"Entity owner\""
1006 "classname 5: \"Method Param\""
1007 "classname 6: \"Method Res\""
1008 "classname 7: \"Super\""
1009 "classname 8: \"Union\""
1010 "classname 9: \"Points-to\""
1011 "classname 10: \"Array Element Type\""
1012 "classname 11: \"Overwrites\""
1013 "classname 12: \"Member\""
1016 xfprintf (F, "\n"); /* a separator */
1019 void vcg_open_name (const char *name) {
1020 char *fname; /* filename to put the vcg information in */
1024 /** open file for vcg graph */
1026 fname = malloc (len + 5);
1027 if (dump_file_suffix)
1028 fname = malloc (len + 5 + strlen(dump_file_suffix));
1030 fname = malloc (len + 5);
1031 strcpy (fname, name); /* copy the filename */
1032 if (dump_file_suffix) strcat (fname, dump_file_suffix);
1033 strcat (fname, ".vcg"); /* append the .vcg suffix */
1034 F = fopen (fname, "w"); /* open file for writing */
1036 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1040 strcpy(label, "yes");
1042 strcpy (label, "no");
1047 "graph: { title: \"ir graph of %s\"\n"
1048 "display_edge_labels: %s\n"
1049 "layoutalgorithm: mindepth\n"
1050 "manhattan_edges: yes\n"
1051 "port_sharing: no\n"
1052 "orientation: bottom_to_top\n"
1053 "classname 1: \"Data\"\n"
1054 "classname 2: \"Block\"\n"
1055 "classname 3: \"Entity type\"\n"
1056 "classname 4: \"Entity owner\"\n"
1057 "classname 5: \"Method Param\"\n"
1058 "classname 6: \"Method Res\"\n"
1059 "classname 7: \"Super\"\n"
1060 "classname 8: \"Union\"\n"
1061 "classname 9: \"Points-to\"\n"
1062 "classname 10: \"Array Element Type\"\n"
1063 "classname 11: \"Overwrites\"\n"
1064 "classname 12: \"Member\"\n"
1067 xfprintf (F, "\n"); /* a separator */
1072 xfprintf (F, "}\n"); /* print footer */
1073 fclose (F); /* close vcg file */
1076 /************************************************************************/
1077 /* routines to dump a graph, blocks as conventional nodes. */
1078 /************************************************************************/
1080 int node_floats(ir_node *n) {
1081 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1082 (get_irg_pinned(current_ir_graph) == floats));
1086 dump_whole_node (ir_node *n, void* env) {
1088 if (!node_floats(n)) dump_ir_block_edge(n);
1089 dump_ir_data_edges(n);
1093 dump_ir_graph (ir_graph *irg)
1096 rem = current_ir_graph;
1097 current_ir_graph = irg;
1101 /* walk over the graph */
1102 /* dump_whole_node must be called in post visiting predecessors */
1103 irg_walk(irg->end, NULL, dump_whole_node, NULL);
1105 /* dump the out edges in a separate walk */
1106 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1107 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
1112 current_ir_graph = rem;
1115 /***********************************************************************/
1116 /* the following routines dump the nodes as attached to the blocks. */
1117 /***********************************************************************/
1120 dump_ir_blocks_nodes (ir_node *n, void *env) {
1121 ir_node *block = (ir_node *)env;
1123 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1125 dump_ir_data_edges(n);
1127 if (get_irn_op(n) == op_Bad)
1132 dump_ir_block (ir_node *block, void *env) {
1133 ir_graph *irg = (ir_graph *)env;
1135 if (get_irn_opcode(block) == iro_Block) {
1137 /* This is a block. So dump the vcg information to make a block. */
1138 xfprintf(F, "graph: { title: \"");
1139 PRINT_NODEID(block);
1140 fprintf(F, "\" label: \"");
1141 #ifdef DEBUG_libfirm
1142 xfprintf (F, "%ld", get_irn_node_nr(block));
1144 xfprintf (F, "%I", block->op->name);
1146 if (exc_normal != get_Block_exc (block))
1147 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1149 xfprintf(F, "\" status:clustered color:%s \n",
1150 get_Block_matured (block) ? "yellow" : "red");
1151 /* dump the blocks edges */
1152 dump_ir_data_edges(block);
1154 /* dump the nodes that go into the block */
1155 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1157 /* Close the vcg information for the block */
1158 xfprintf(F, "}\n\n");
1159 dump_const_node_local(block, NULL);
1165 dump_blockless_nodes (ir_node *n, void *env) {
1166 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1168 dump_ir_data_edges(n);
1169 dump_ir_block_edge(n);
1170 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1173 if (node_floats(n)) {
1175 dump_ir_data_edges(n);
1176 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1180 void dump_ir_block_graph_2 (ir_graph *irg)
1183 /* walk over the blocks in the graph */
1184 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1186 /* dump all nodes that are not in a Block */
1187 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1189 /* dump the Bad node */
1191 dump_node(get_irg_bad(irg), NULL);
1195 dump_ir_block_graph (ir_graph *irg)
1198 rem = current_ir_graph;
1199 current_ir_graph = irg;
1203 dump_ir_block_graph_2 (irg);
1205 if (dump_loop_information_flag) dump_loop_info(irg);
1208 current_ir_graph = rem;
1212 /***********************************************************************/
1213 /* the following routines dump a control flow graph */
1214 /***********************************************************************/
1218 dump_block_to_cfg (ir_node *block, void *env) {
1222 if (get_irn_opcode(block) == iro_Block) {
1223 /* This is a block. Dump a node for the block. */
1224 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1225 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1227 if (exc_normal != get_Block_exc (block))
1228 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1230 xfprintf (F, "\" ");
1231 if (dump_dominator_information_flag)
1232 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1233 xfprintf (F, "}\n");
1234 /* Dump the edges */
1235 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1236 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1237 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1238 xfprintf (F, "edge: { sourcename: \"");
1239 PRINT_NODEID(block);
1240 fprintf (F, "\" targetname: \"");
1242 fprintf (F, "\" }\n");
1245 /* Dump dominator edge */
1246 if (dump_dominator_information_flag && get_Block_idom(block)) {
1247 pred = get_Block_idom(block);
1248 xfprintf (F, "edge: { sourcename: \"");
1249 PRINT_NODEID(block);
1250 fprintf (F, "\" targetname: \"");
1252 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1258 dump_cfg (ir_graph *irg)
1260 ir_graph *rem = current_ir_graph;
1261 int ddif = dump_dominator_information_flag;
1262 current_ir_graph = irg;
1263 vcg_open (irg, "-cfg");
1265 if (get_irg_dom_state(irg) != dom_consistent)
1266 dump_dominator_information_flag = 0;
1268 /* walk over the blocks in the graph */
1269 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1270 dump_ir_node (irg->bad);
1272 dump_dominator_information_flag = ddif;
1274 current_ir_graph = rem;
1278 /***********************************************************************/
1279 /* the following routine dumps all type information reachable from an */
1281 /***********************************************************************/
1285 dump_type_graph (ir_graph *irg)
1288 rem = current_ir_graph;
1289 current_ir_graph = irg;
1291 vcg_open (irg, "-type");
1293 /* walk over the blocks in the graph */
1294 type_walk_irg(irg, dump_type_info, NULL, NULL);
1295 /* The walker for the const code can be called several times for the
1296 same (sub) experssion. So that no nodes are dumped several times
1297 we decrease the visited flag of the corresponding graph after each
1298 walk. So now increase it finally. */
1299 inc_irg_visited(get_const_code_irg());
1302 current_ir_graph = rem;
1305 /***********************************************************************/
1306 /* the following routine dumps all type information */
1307 /***********************************************************************/
1311 dump_all_types (void)
1313 vcg_open_name ("All_types");
1314 type_walk(dump_type_info, NULL, NULL);
1315 inc_irg_visited(get_const_code_irg());
1319 /***********************************************************************/
1320 /* dumps a graph with type information */
1321 /***********************************************************************/
1325 dump_ir_graph_w_types (ir_graph *irg)
1328 rem = current_ir_graph;
1329 current_ir_graph = irg;
1331 vcg_open (irg, "-all");
1333 /* dump common ir graph */
1334 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1335 /* dump type info */
1336 type_walk_irg(irg, dump_type_info, NULL, NULL);
1337 inc_irg_visited(get_const_code_irg());
1338 /* dump edges from graph to type info */
1339 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1342 current_ir_graph = rem;
1346 dump_ir_block_graph_w_types (ir_graph *irg)
1349 rem = current_ir_graph;
1350 current_ir_graph = irg;
1352 vcg_open (irg, "-all");
1354 /* dump common blocked ir graph */
1355 dump_ir_block_graph_2(irg);
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(irg->end, dump_node2type_edges, NULL, NULL);
1363 current_ir_graph = rem;
1366 /***********************************************************************/
1367 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1369 /* dump_ir_block_graph */
1371 /* dump_type_graph */
1372 /* dump_ir_graph_w_types */
1373 /***********************************************************************/
1374 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1376 for (i=0; i < get_irp_n_irgs(); i++) {
1377 dump_graph(get_irp_irg(i));
1382 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1383 abort with a segmentation fault. */
1384 void turn_off_edge_labels() {
1389 void dump_consts_local(bool b) {
1390 dump_const_local = b;
1393 void turn_off_constant_entity_values() {
1397 void dump_keepalive_edges() {
1401 void dump_out_edges() {
1402 dump_out_edge_flag = 1;
1405 void dump_dominator_information() {
1406 dump_dominator_information_flag = 1;
1409 void dump_loop_information() {
1410 dump_loop_information_flag = 1;
1413 void dont_dump_loop_information() {
1414 dump_loop_information_flag = 0;
1417 static void clear_link(ir_node * node, void * env) {
1418 set_irn_link(node, NULL);
1421 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1423 || node_floats(node)
1424 || get_irn_op(node) == op_Bad
1425 || get_irn_op(node) == op_Unknown) {
1426 pmap_entry * entry = pmap_find(map, current_ir_graph);
1428 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1430 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1432 pmap_insert(map, current_ir_graph, arr);
1435 ir_node * block = get_nodes_Block(node);
1436 set_irn_link(node, get_irn_link(block));
1437 set_irn_link(block, node);
1442 static void dump_cg_ir_block(ir_node * block, void * env) {
1444 pmap *irgmap = (pmap *)env;
1445 assert(is_Block(block));
1446 xfprintf(F, "graph: { title: \"");
1447 PRINT_NODEID(block);
1448 fprintf(F, "\" label: \"");
1449 #ifdef DEBUG_libfirm
1450 xfprintf (F, "%ld", get_irn_node_nr(block));
1452 xfprintf (F, "%I", block->op->name);
1454 if (exc_normal != get_Block_exc(block)) {
1455 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1458 xfprintf(F, "\" status:clustered color:%s \n",
1459 get_Block_matured(block) ? "yellow" : "red");
1461 /* dump the blocks edges */
1462 dump_ir_data_edges(block);
1464 /* dump the nodes that go into the block */
1465 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1466 dump_node(node, irgmap);
1467 dump_ir_data_edges(node);
1470 /* Close the vcg information for the block */
1471 xfprintf(F, "}\n\n");
1474 void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1477 xfprintf(F, "graph: { title: \"%p\" label: \"%I\" status:clustered color:white \n",
1478 irg, get_entity_ident(get_irg_ent(irg)));
1480 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1481 ir_node * node = arr[i];
1482 if (is_Block(node)) {
1483 /* Dumps the block and all the nodes in the block , which are to
1484 be found in Block->link. */
1485 dump_cg_ir_block(node, irgmap);
1487 /* Nodes that are not in a Block. */
1488 dump_node(node, NULL);
1489 dump_ir_data_edges(node);
1492 /* Close the vcg information for the irg */
1493 xfprintf(F, "}\n\n");
1496 /* dump interprocedural graph with surrounding methods */
1497 void dump_cg_block_graph(ir_graph * irg) {
1498 pmap * map = pmap_create();
1499 pmap * map2 = pmap_create();
1504 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1505 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1506 pmap_insert(map2, entry->key, entry->value);
1507 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1508 d_cg_block_graph(entry->key, entry->value, map2);
1509 DEL_ARR_F(entry->value);
1515 if (dump_loop_information_flag) dump_loop_info(irg);
1519 static void collect_node(ir_node * node, void *env) {
1521 || node_floats(node)
1522 || get_irn_op(node) == op_Bad
1523 || get_irn_op(node) == op_Unknown) {
1524 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1525 ARR_APP1(ir_node *, arr, node);
1526 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1528 ir_node * block = get_nodes_Block(node);
1529 set_irn_link(node, get_irn_link(block));
1530 set_irn_link(block, node);
1534 /* Links all nodes that have the block field set in the link field of
1535 the block. Adds all blocks and nodes not associated with a block
1536 in a array in irg->link. */
1537 static void collect_nodes() {
1539 for (i = 0; i < get_irp_n_irgs(); i++)
1540 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1541 cg_walk(clear_link, collect_node, NULL);
1544 static void dump_graphs() {
1546 for (i = 0; i < get_irp_n_irgs(); i++) {
1547 current_ir_graph = get_irp_irg(i);
1548 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1552 /* Dump all irgs in interprocedural view to a single file. */
1553 void dump_all_cg_block_graph() {
1555 int rem_view = interprocedural_view;
1556 interprocedural_view = 1;
1557 vcg_open_name ("All_graphs");
1562 if (dump_loop_information_flag)
1563 for (i = 0; i < get_irp_n_irgs(); i++)
1564 dump_loop_info(get_irp_irg(i));
1567 interprocedural_view = rem_view;
1570 /* dump interprocedural block graph with surrounding methods */
1571 void dump_cg_graph(ir_graph * irg) {
1572 pmap * map = pmap_create();
1573 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1577 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1578 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1579 pmap_insert(map2, entry->key, entry->value);
1580 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1581 ir_node ** arr = entry->value;
1583 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1585 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1586 irg_ident, irg_ident);
1588 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1589 ir_node * node = arr[i];
1590 dump_node(node, map2);
1591 dump_ir_data_edges(node);
1592 if (is_Block(node)) {
1593 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1594 dump_node(node, map2);
1595 dump_ir_block_edge(node);
1596 dump_ir_data_edges(node);
1603 /* Close the vcg information for the irg */
1604 xfprintf(F, "}\n\n");