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;
96 /* A global variable to record output of the Bad node. */
99 void dump_ir_blocks_nodes (ir_node *n, void *env);
100 void dump_whole_node (ir_node *n, void* env);
102 /*******************************************************************/
103 /* routines to dump information about a single node */
104 /*******************************************************************/
109 dump_node_opcode (ir_node *n)
114 if (n->op->code == iro_Const) {
115 xfprintf (F, "%v", n->attr.con);
118 } else if (n->op->code == iro_SymConst) {
119 if (get_SymConst_kind(n) == linkage_ptr_info) {
120 /* don't use get_SymConst_ptr_info as it mangles the name. */
121 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
123 assert(get_kind(get_SymConst_type(n)) == k_type);
124 assert(get_type_ident(get_SymConst_type(n)));
125 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
126 if (get_SymConst_kind == type_tag)
129 xfprintf (F, "size");
133 } else if (n->op->code == iro_Filter && !interprocedural_view) {
138 xfprintf (F, "%I", get_irn_opident(n));
143 dump_node_mode (ir_node *n)
145 switch (n->op->code) {
163 xfprintf (F, "%I", get_mode_ident(n->mode));
169 void dump_node_loop_info(ir_node *n) {
170 // if (get_irn_loop(n))
171 // xfprintf(F, "\n in loop %d", get_loop_depth(get_irn_loop(n)));
175 dump_node_nodeattr (ir_node *n)
177 switch (n->op->code) {
179 if (false && interprocedural_view) {
180 xfprintf (F, "%I", get_entity_ident(get_irg_ent(current_ir_graph)));
184 if (n->in[1]->op->code == iro_Cmp) {
185 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
187 xfprintf (F, "%ld", n->attr.proj);
191 xfprintf (F, "%ld", n->attr.filter.proj);
194 assert(get_kind(get_Sel_entity(n)) == k_entity);
195 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
202 dump_node_vcgattr (ir_node *n)
204 switch (n->op->code) {
211 xfprintf (F, "color: blue");
214 xfprintf (F, "color: lightyellow");
217 xfprintf (F, "color: green");
223 xfprintf (F, "color: yellow");
226 xfprintf (F, DEFAULT_NODE_ATTR);
231 dump_node (ir_node *n) {
234 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
238 //if (dump_loop_information_flag) dump_node_loop_info(n);
240 dump_node_nodeattr(n);
242 xfprintf (F, " %ld", get_irn_node_nr(n));
245 dump_node_vcgattr(n);
250 dump_ir_node (ir_node *n)
253 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
255 switch (n->op->code) { /* node label */
257 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
258 xfprintf (F, DEFAULT_NODE_ATTR);
265 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
266 xfprintf (F, DEFAULT_NODE_ATTR);
269 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
270 xfprintf (F, DEFAULT_NODE_ATTR);
273 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
274 if (get_irn_modecode(n) == irm_M)
275 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
277 xfprintf (F, DEFAULT_NODE_ATTR);
280 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
281 xfprintf (F, DEFAULT_NODE_ATTR);
284 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
285 xfprintf (F, DEFAULT_NODE_ATTR);
288 if (n->in[1]->op->code == iro_Cmp) {
289 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
290 get_pnc_string(n->attr.proj));
292 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
294 xfprintf (F, DEFAULT_NODE_ATTR);
297 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.filter.proj);
298 xfprintf (F, DEFAULT_NODE_ATTR);
301 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
302 xfprintf (F, DEFAULT_NODE_ATTR);
305 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
306 xfprintf (F, DEFAULT_NODE_ATTR);
309 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
310 xfprintf (F, DEFAULT_NODE_ATTR);
313 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
314 xfprintf (F, DEFAULT_NODE_ATTR);
317 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
318 xfprintf (F, DEFAULT_NODE_ATTR);
321 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
322 xfprintf (F, DEFAULT_NODE_ATTR);
325 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
326 xfprintf (F, DEFAULT_NODE_ATTR);
329 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
330 xfprintf (F, DEFAULT_NODE_ATTR);
333 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
334 xfprintf (F, DEFAULT_NODE_ATTR);
337 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
338 xfprintf (F, DEFAULT_NODE_ATTR);
341 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
342 xfprintf (F, DEFAULT_NODE_ATTR);
345 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
346 xfprintf (F, DEFAULT_NODE_ATTR);
349 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
350 xfprintf (F, DEFAULT_NODE_ATTR);
353 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
354 xfprintf (F, DEFAULT_NODE_ATTR);
357 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
358 xfprintf (F, DEFAULT_NODE_ATTR);
361 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
362 xfprintf (F, DEFAULT_NODE_ATTR);
365 xfprintf (F, "\"%I\"", get_irn_opident(n));
366 xfprintf (F, DEFAULT_NODE_ATTR);
369 xfprintf (F, "\"%I\"", get_irn_opident(n));
370 xfprintf (F, DEFAULT_NODE_ATTR);
373 xfprintf (F, "\"%I\"", get_irn_opident(n));
374 xfprintf (F, DEFAULT_NODE_ATTR);
377 xfprintf (F, "\"%I\"", get_irn_opident(n));
378 xfprintf (F, DEFAULT_NODE_ATTR);
381 xfprintf (F, "\"%I\"", get_irn_opident(n));
382 xfprintf (F, DEFAULT_NODE_ATTR);
385 xfprintf (F, "\"%I\"", get_irn_opident(n));
386 xfprintf (F, DEFAULT_NODE_ATTR);
389 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
390 xfprintf (F, DEFAULT_NODE_ATTR);
394 xfprintf (F, "\"%R\"", n);
395 xfprintf (F, DEFAULT_NODE_ATTR);
398 xfprintf (F, "\"%I\" ", get_irn_opident(n));
399 xfprintf (F, DEFAULT_NODE_ATTR);
402 assert(get_kind(get_Sel_entity(n)) == k_entity);
403 xfprintf (F, "\"%I ", get_irn_opident(n));
404 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
405 xfprintf (F, DEFAULT_NODE_ATTR);
408 assert(get_kind(get_SymConst_type(n)) == k_type);
409 assert(get_type_ident(get_SymConst_type(n)));
410 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
411 switch (n->attr.i.num){
413 xfprintf (F, "tag\" ");
416 xfprintf (F, "size\" ");
422 xfprintf (F, DEFAULT_NODE_ATTR);
425 xfprintf (F, "\"%I\" ", get_irn_opident(n));
426 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
429 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
430 xfprintf (F, DEFAULT_NODE_ATTR);
433 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
434 xfprintf (F, DEFAULT_NODE_ATTR);
437 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
439 xfprintf (F, "}\n"); /* footer */
443 /* dump the edge to the block this node belongs to */
445 dump_ir_block_edge(ir_node *n) {
446 if (is_no_Block(n)) {
447 xfprintf (F, "edge: { sourcename: \"");
449 xfprintf (F, "\" targetname: \"");
450 PRINT_NODEID(get_nodes_Block(n));
451 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
455 void print_edge_vcgattr(ir_node *from, int to) {
458 if (is_backedge(from, to)) xfprintf (F, BACK_EDGE_ATTR);
460 switch (get_irn_opcode(from)) {
462 xfprintf (F, CF_EDGE_ATTR);
464 case iro_Start: break;
467 if (get_irn_mode(get_End_keepalive(from, to)) == mode_R)
468 xfprintf (F, CF_EDGE_ATTR);
469 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
470 xfprintf (F, MEM_EDGE_ATTR);
473 case iro_EndReg: break;
474 case iro_EndExcept: break;
476 case iro_Break: break;
477 case iro_Cond: break;
480 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
482 case iro_Const: break;
483 case iro_SymConst:break;
486 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
488 case iro_CallBegin: break;
491 case iro_Minus: break;
497 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
505 case iro_Shrs: break;
508 case iro_Conv: break;
510 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
516 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
519 xfprintf (F, MEM_EDGE_ATTR);
521 case iro_Tuple: break;
524 switch (get_irn_modecode(from)) {
526 xfprintf (F, CF_EDGE_ATTR);
529 xfprintf (F, MEM_EDGE_ATTR);
535 case iro_Unknown: break;
541 /* dump edges to our inputs */
543 dump_ir_data_edges(ir_node *n) {
544 int i, visited = get_irn_visited(n);
546 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
549 for (i = 0; i < get_irn_arity(n); i++) {
550 ir_node * pred = get_irn_n(n, i);
552 if (interprocedural_view && get_irn_visited(pred) < visited)
553 continue; /* pred not dumped */
554 if (is_backedge(n, i))
555 fprintf (F, "backedge: {sourcename: \"");
557 fprintf (F, "edge: {sourcename: \"");
559 fprintf (F, "\" targetname: \"");
562 fprintf (F, " label: \"%d\" ", i);
563 print_edge_vcgattr(n, i);
570 dump_out_edge (ir_node *n, void* env) {
572 for (i = 0; i < get_irn_n_outs(n); i++) {
573 assert(get_irn_out(n, i));
574 fprintf (F, "edge: {sourcename: \"");
576 fprintf (F, "\" targetname: \"");
577 PRINT_NODEID(get_irn_out(n, i));
578 fprintf (F, "\" color: red linestyle: dashed");
584 dump_loop_node_edge (ir_loop *loop, int i) {
586 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", loop);
587 PRINT_NODEID(get_loop_node(loop, i));
588 fprintf (F, "\" color: green");
593 void dump_loops (ir_loop *loop) {
595 /* dump this loop node */
596 xfprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
597 loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
598 /* dump edges to nodes in loop -- only if it is a real loop */
599 if (get_loop_depth(loop) != 0) {
600 for (i = 0; i < get_loop_n_nodes(loop); i++) {
601 dump_loop_node_edge(loop, i);
604 for (i = 0; i < get_loop_n_sons(loop); i++) {
605 dump_loops(get_loop_son(loop, i));
610 void dump_loop_info(ir_graph *irg) {
611 ir_graph *rem = current_ir_graph;
612 current_ir_graph = irg;
614 if (get_irg_loop(irg))
615 dump_loops(get_irg_loop(irg));
617 current_ir_graph = rem;
621 /* dumps the edges between nodes and their type or entity attributes. */
622 void dump_node2type_edges (ir_node *n, void *env)
626 switch (get_irn_opcode(n)) {
628 /* @@@ some consts have an entity */
631 if ( (get_SymConst_kind(n) == type_tag)
632 || (get_SymConst_kind(n) == size)) {
633 xfprintf (F, "edge: { sourcename: \"");
635 fprintf (F, "\" targetname: \"%p\" "
636 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
640 xfprintf (F, "edge: { sourcename: \"");
642 fprintf (F, "\" targetname: \"%p\" "
643 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
646 xfprintf (F, "edge: { sourcename: \"");
648 fprintf (F, "\" targetname: \"%p\" "
649 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
652 xfprintf (F, "edge: { sourcename: \"");
654 fprintf (F, "\" targetname: \"%p\" "
655 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
658 xfprintf (F, "edge: { sourcename: \"");
660 fprintf (F, "\" targetname: \"%p\" "
661 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
669 void dump_const_expression(ir_node *value) {
670 ir_graph *rem = current_ir_graph;
671 current_ir_graph = get_const_code_irg();
672 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
673 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
674 current_ir_graph = rem;
678 void print_type_info(type *tp) {
679 if (get_type_state(tp) == layout_undefined) {
680 xfprintf(F, "state: layout_undefined\n");
682 xfprintf(F, "state: layout_fixed,\n");
684 if (get_type_mode(tp))
685 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
686 xfprintf(F, "size: %dB,\n", get_type_size(tp));
690 void print_typespecific_info(type *tp) {
691 switch (get_type_tpop_code(tp)) {
694 if(existent == get_class_peculiarity(tp))
695 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
697 xfprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
701 xfprintf (F, " " TYPE_METH_NODE_ATTR);
712 case tpo_enumeration:
725 void print_type_node(type *tp) {
726 xfprintf (F, "node: {title: \"%p\" ", tp);
727 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
728 xfprintf (F, "info1: \"");
731 print_typespecific_info(tp);
735 /* dumps a type or entity and it's edges. */
737 dump_type_info (type_or_ent *tore, void *env) {
738 int i = 0; /* to shutup gcc */
740 /* dump this type or entity */
742 switch (get_kind(tore)) {
745 entity *ent = (entity *)tore;
748 xfprintf (F, "node: {title: \"%p\" ", tore);
749 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
750 xfprintf (F, "label: ");
751 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
752 switch (get_entity_allocation(ent)) {
753 case dynamic_allocated: fprintf (F, " info1:\"dynamic allocated\n"); break;
754 case automatic_allocated: fprintf (F, " info1:\"automatic allocated\n"); break;
755 case static_allocated: fprintf (F, " info1:\"static allocated\n"); break;
757 switch (get_entity_visibility(ent)) {
758 case local: fprintf (F, "local\n"); break;
759 case external_visible: fprintf (F, "external_visible\n"); break;
760 case external_allocated: fprintf (F, "external_allocate\n"); break;
762 switch (get_entity_variability(ent)) {
763 case uninitialized: fprintf (F, "uninitialized\n");break;
764 case initialized: fprintf (F, "initialized\n"); break;
765 case part_constant: fprintf (F, "part_constant\n");break;
766 case constant: fprintf (F, "constant\n"); break;
768 switch (get_entity_volatility(ent)) {
769 case non_volatile: fprintf (F, "non_volatile\n"); break;
770 case is_volatile: fprintf (F, "is_volatile\n"); break;
772 switch (get_entity_peculiarity(ent)) {
773 case description: fprintf (F, "description\n"); break;
774 case inherited: fprintf (F, "inherited\n"); break;
775 case existent: fprintf (F, "existent\n"); break;
777 if (is_method_type(get_entity_type(ent)))
778 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
779 xfprintf(F, "\"}\n");
781 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
782 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
783 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
784 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
785 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
786 if(is_class_type(get_entity_owner(ent))) {
787 for(i = 0; i < get_entity_n_overwrites(ent); i++)
788 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
789 ENT_OVERWRITES_EDGE_ATTR "}\n",
790 ent, get_entity_overwrites(ent, i));
792 /* attached subgraphs */
793 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
794 if (is_atomic_entity(ent)) {
795 value = get_atomic_ent_value(ent);
796 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
798 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
799 dump_const_expression(value);
801 if (is_compound_entity(ent)) {
802 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
803 value = get_compound_ent_value(ent, i);
804 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
806 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
807 dump_const_expression(value);
808 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
809 ENT_CORR_EDGE_ATTR "}\n", ent,
810 get_compound_ent_value_member(ent, i), i);
817 type *tp = (type *)tore;
819 /* and now the edges */
820 switch (get_type_tpop_code(tp)) {
823 for (i=0; i < get_class_n_supertypes(tp); i++)
824 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
825 TYPE_SUPER_EDGE_ATTR "}\n",
826 tp, get_class_supertype(tp, i));
827 for (i=0; i < get_class_n_members(tp); i++)
828 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
829 TYPE_MEMBER_EDGE_ATTR "}\n",
830 tp, get_class_member(tp, i));
834 for (i=0; i < get_struct_n_members(tp); i++)
835 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
836 TYPE_MEMBER_EDGE_ATTR "}\n",
837 tp, get_struct_member(tp, i));
841 for (i = 0; i < get_method_n_params(tp); i++)
842 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
843 METH_PAR_EDGE_ATTR "}\n",
844 tp, get_method_param_type(tp, i), i);
845 for (i = 0; i < get_method_n_ress(tp); i++)
846 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
847 METH_RES_EDGE_ATTR "}\n",
848 tp, get_method_res_type(tp, i), i);
852 for (i = 0; i < get_union_n_members(tp); i++)
853 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
854 "label: \"\"f" UNION_EDGE_ATTR "}\n",
855 tp, get_union_member(tp, i));
859 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
860 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
861 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
862 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
864 case tpo_enumeration:
869 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
870 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
871 get_pointer_points_to_type(tp), i);
879 break; /* case k_type */
882 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
884 } /* switch kind_or_entity */
887 /************************************************************************/
888 /* open and close vcg file */
889 /************************************************************************/
891 void vcg_open (ir_graph *irg, char *suffix) {
892 char *fname; /* filename to put the vcg information in */
899 /** open file for vcg graph */
900 ent = get_irg_ent(irg);
901 id = ent->ld_name ? ent->ld_name : ent->name;
902 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
903 len = id_to_strlen (id);
905 if (dump_file_suffix)
906 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
908 fname = malloc (len + 5 + strlen(suffix));
909 strncpy (fname, cp, len); /* copy the filename */
911 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
912 strcat (fname, suffix); /* append file suffix */
913 strcat (fname, ".vcg"); /* append the .vcg suffix */
914 F = fopen (fname, "w"); /* open file for writing */
916 panic ("cannot open %s for writing (%m)", fname); /* not reached */
920 strcpy(label, "yes");
922 strcpy (label, "no");
927 "graph: { title: \"ir graph of %s\"\n"
928 "display_edge_labels: %s\n"
929 "layoutalgorithm: mindepth\n"
930 "manhattan_edges: yes\n"
932 "orientation: bottom_to_top\n"
933 "classname 1: \"Data\"\n"
934 "classname 2: \"Block\"\n"
935 "classname 3: \"Entity type\""
936 "classname 4: \"Entity owner\""
937 "classname 5: \"Method Param\""
938 "classname 6: \"Method Res\""
939 "classname 7: \"Super\""
940 "classname 8: \"Union\""
941 "classname 9: \"Points-to\""
942 "classname 10: \"Array Element Type\""
943 "classname 11: \"Overwrites\""
944 "classname 12: \"Member\""
947 xfprintf (F, "\n"); /* a separator */
950 void vcg_open_name (const char *name) {
951 char *fname; /* filename to put the vcg information in */
955 /** open file for vcg graph */
957 fname = malloc (len + 5);
958 if (dump_file_suffix)
959 fname = malloc (len + 5 + strlen(dump_file_suffix));
961 fname = malloc (len + 5);
962 strcpy (fname, name); /* copy the filename */
963 if (dump_file_suffix) strcat (fname, dump_file_suffix);
964 strcat (fname, ".vcg"); /* append the .vcg suffix */
965 F = fopen (fname, "w"); /* open file for writing */
967 panic ("cannot open %s for writing (%m)", fname); /* not reached */
971 strcpy(label, "yes");
973 strcpy (label, "no");
978 "graph: { title: \"ir graph of %s\"\n"
979 "display_edge_labels: %s\n"
980 "layoutalgorithm: mindepth\n"
981 "manhattan_edges: yes\n"
983 "orientation: bottom_to_top\n"
984 "classname 1: \"Data\"\n"
985 "classname 2: \"Block\"\n"
986 "classname 3: \"Entity type\"\n"
987 "classname 4: \"Entity owner\"\n"
988 "classname 5: \"Method Param\"\n"
989 "classname 6: \"Method Res\"\n"
990 "classname 7: \"Super\"\n"
991 "classname 8: \"Union\"\n"
992 "classname 9: \"Points-to\"\n"
993 "classname 10: \"Array Element Type\"\n"
994 "classname 11: \"Overwrites\"\n"
995 "classname 12: \"Member\"\n"
998 xfprintf (F, "\n"); /* a separator */
1003 xfprintf (F, "}\n"); /* print footer */
1004 fclose (F); /* close vcg file */
1007 /************************************************************************/
1008 /* routines to dump a graph, blocks as conventional nodes. */
1009 /************************************************************************/
1011 int node_floats(ir_node *n) {
1012 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1013 (get_irg_pinned(current_ir_graph) == floats));
1017 dump_whole_node (ir_node *n, void* env) {
1019 if (!node_floats(n)) dump_ir_block_edge(n);
1020 dump_ir_data_edges(n);
1024 dump_ir_graph (ir_graph *irg)
1027 rem = current_ir_graph;
1028 current_ir_graph = irg;
1032 /* walk over the graph */
1033 /* dump_whole_node must be called in post visiting predecessors */
1034 irg_walk(irg->end, NULL, dump_whole_node, NULL);
1036 /* dump the out edges in a separate walk */
1037 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1038 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
1043 current_ir_graph = rem;
1046 /***********************************************************************/
1047 /* the following routines dump the nodes as attached to the blocks. */
1048 /***********************************************************************/
1051 dump_ir_blocks_nodes (ir_node *n, void *env) {
1052 ir_node *block = (ir_node *)env;
1054 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1056 dump_ir_data_edges(n);
1058 if (get_irn_op(n) == op_Bad)
1063 dump_ir_block (ir_node *block, void *env) {
1064 ir_graph *irg = (ir_graph *)env;
1066 if (get_irn_opcode(block) == iro_Block) {
1068 /* This is a block. So dump the vcg information to make a block. */
1069 xfprintf(F, "graph: { title: \"");
1070 PRINT_NODEID(block);
1071 fprintf(F, "\" label: \"");
1072 #ifdef DEBUG_libfirm
1073 xfprintf (F, "%ld", get_irn_node_nr(block));
1075 xfprintf (F, "%I", block->op->name);
1077 if (exc_normal != get_Block_exc (block))
1078 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1080 xfprintf(F, "\" status:clustered color:%s \n",
1081 get_Block_matured (block) ? "yellow" : "red");
1082 /* dump the blocks edges */
1083 dump_ir_data_edges(block);
1085 /* dump the nodes that go into the block */
1086 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1088 /* Close the vcg information for the block */
1089 xfprintf(F, "}\n\n");
1095 dump_blockless_nodes (ir_node *n, void *env) {
1096 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1098 dump_ir_data_edges(n);
1099 dump_ir_block_edge(n);
1100 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1103 if (node_floats(n)) {
1105 dump_ir_data_edges(n);
1106 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1110 void dump_ir_block_graph_2 (ir_graph *irg)
1113 /* walk over the blocks in the graph */
1114 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1116 /* dump all nodes that are not in a Block */
1117 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1119 /* dump the Bad node */
1121 dump_node(get_irg_bad(irg));
1125 dump_ir_block_graph (ir_graph *irg)
1128 rem = current_ir_graph;
1129 current_ir_graph = irg;
1133 dump_ir_block_graph_2 (irg);
1135 if (dump_loop_information_flag) {
1136 dump_loop_info(irg);
1140 current_ir_graph = rem;
1144 /***********************************************************************/
1145 /* the following routines dump a control flow graph */
1146 /***********************************************************************/
1150 dump_block_to_cfg (ir_node *block, void *env) {
1154 if (get_irn_opcode(block) == iro_Block) {
1155 /* This is a block. Dump a node for the block. */
1156 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1157 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1159 if (exc_normal != get_Block_exc (block))
1160 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1162 xfprintf (F, "\" ");
1163 if (dump_dominator_information_flag)
1164 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1165 xfprintf (F, "}\n");
1166 /* Dump the edges */
1167 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1168 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1169 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1170 xfprintf (F, "edge: { sourcename: \"");
1171 PRINT_NODEID(block);
1172 fprintf (F, "\" targetname: \"");
1174 fprintf (F, "\" }\n");
1177 /* Dump dominator edge */
1178 if (dump_dominator_information_flag && get_Block_idom(block)) {
1179 pred = get_Block_idom(block);
1180 xfprintf (F, "edge: { sourcename: \"");
1181 PRINT_NODEID(block);
1182 fprintf (F, "\" targetname: \"");
1184 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1190 dump_cfg (ir_graph *irg)
1192 ir_graph *rem = current_ir_graph;
1193 int ddif = dump_dominator_information_flag;
1194 current_ir_graph = irg;
1195 vcg_open (irg, "-cfg");
1197 if (get_irg_dom_state(irg) != dom_consistent)
1198 dump_dominator_information_flag = 0;
1200 /* walk over the blocks in the graph */
1201 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1202 dump_ir_node (irg->bad);
1204 dump_dominator_information_flag = ddif;
1206 current_ir_graph = rem;
1210 /***********************************************************************/
1211 /* the following routine dumps all type information reachable from an */
1213 /***********************************************************************/
1217 dump_type_graph (ir_graph *irg)
1220 rem = current_ir_graph;
1221 current_ir_graph = irg;
1223 vcg_open (irg, "-type");
1225 /* walk over the blocks in the graph */
1226 type_walk_irg(irg, dump_type_info, NULL, NULL);
1227 /* The walker for the const code can be called several times for the
1228 same (sub) experssion. So that no nodes are dumped several times
1229 we decrease the visited flag of the corresponding graph after each
1230 walk. So now increase it finally. */
1231 inc_irg_visited(get_const_code_irg());
1234 current_ir_graph = rem;
1237 /***********************************************************************/
1238 /* the following routine dumps all type information */
1239 /***********************************************************************/
1243 dump_all_types (void)
1245 vcg_open_name ("All_types");
1246 type_walk(dump_type_info, NULL, NULL);
1247 inc_irg_visited(get_const_code_irg());
1251 /***********************************************************************/
1252 /* dumps a graph with type information */
1253 /***********************************************************************/
1257 dump_ir_graph_w_types (ir_graph *irg)
1260 rem = current_ir_graph;
1261 current_ir_graph = irg;
1263 vcg_open (irg, "-all");
1265 /* dump common ir graph */
1266 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1267 /* dump type info */
1268 type_walk_irg(irg, dump_type_info, NULL, NULL);
1269 inc_irg_visited(get_const_code_irg());
1270 /* dump edges from graph to type info */
1271 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1274 current_ir_graph = rem;
1278 dump_ir_block_graph_w_types (ir_graph *irg)
1281 rem = current_ir_graph;
1282 current_ir_graph = irg;
1284 vcg_open (irg, "-all");
1286 /* dump common blocked ir graph */
1287 dump_ir_block_graph_2(irg);
1288 /* dump type info */
1289 type_walk_irg(irg, dump_type_info, NULL, NULL);
1290 inc_irg_visited(get_const_code_irg());
1291 /* dump edges from graph to type info */
1292 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1295 current_ir_graph = rem;
1298 /***********************************************************************/
1299 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1301 /* dump_ir_block_graph */
1303 /* dump_type_graph */
1304 /* dump_ir_graph_w_types */
1305 /***********************************************************************/
1306 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1308 for (i=0; i < get_irp_n_irgs(); i++) {
1309 dump_graph(get_irp_irg(i));
1314 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1315 abort with a segmentation fault. */
1316 void turn_off_edge_labels() {
1320 void turn_off_constant_entity_values() {
1324 void dump_keepalive_edges() {
1328 void dump_out_edges() {
1329 dump_out_edge_flag = 1;
1332 void dump_dominator_information() {
1333 dump_dominator_information_flag = 1;
1336 void dump_loop_information() {
1337 dump_loop_information_flag = 1;
1340 void dont_dump_loop_information() {
1341 dump_loop_information_flag = 0;
1344 static void clear_link(ir_node * node, void * env) {
1345 set_irn_link(node, NULL);
1349 static INLINE bool is_Block(ir_node * node) {
1350 return !is_no_Block(node);
1354 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1356 || node_floats(node)
1357 || get_irn_op(node) == op_Bad
1358 || get_irn_op(node) == op_Unknown) {
1359 pmap_entry * entry = pmap_find(map, current_ir_graph);
1361 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1363 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1365 pmap_insert(map, current_ir_graph, arr);
1368 ir_node * block = get_nodes_Block(node);
1369 set_irn_link(node, get_irn_link(block));
1370 set_irn_link(block, node);
1375 static void dump_cg_ir_block(ir_node * node, void * env) {
1376 assert(is_Block(node));
1377 xfprintf(F, "graph: { title: \"");
1379 fprintf(F, "\" label: \"");
1380 #ifdef DEBUG_libfirm
1381 xfprintf (F, "%ld", get_irn_node_nr(node));
1383 xfprintf (F, "%I", node->op->name);
1385 if (exc_normal != get_Block_exc(node)) {
1386 fprintf (F, " (%s)", exc_to_string (get_Block_exc(node)));
1389 xfprintf(F, "\" status:clustered color:%s \n",
1390 get_Block_matured(node) ? "yellow" : "red");
1392 /* dump the blocks edges */
1393 dump_ir_data_edges(node);
1395 /* dump the nodes that go into the block */
1396 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1398 dump_ir_data_edges(node);
1401 /* Close the vcg information for the block */
1402 xfprintf(F, "}\n\n");
1406 /* dump interprocedural graph with surrounding methods */
1407 void dump_cg_block_graph(ir_graph * irg) {
1408 pmap * map = pmap_create();
1412 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1413 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1414 ir_node ** arr = entry->value;
1417 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1418 get_entity_ident(get_irg_ent(entry->key)),
1419 get_entity_ident(get_irg_ent(entry->key)));
1421 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1422 ir_node * node = arr[i];
1423 if (is_Block(node)) {
1424 /* Dumps the block and all the nodes in the block , with are to be found in
1426 dump_cg_ir_block(node, NULL);
1428 /* Node that are not in a Block. */
1430 dump_ir_data_edges(node);
1436 /* Close the vcg information for the irg */
1437 xfprintf(F, "}\n\n");
1442 if (dump_loop_information_flag) {
1443 dump_loop_info(irg);
1450 /* dump interprocedural block graph with surrounding methods */
1451 void dump_cg_graph(ir_graph * irg) {
1452 pmap * map = pmap_create();
1456 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1457 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1458 ir_node ** arr = entry->value;
1460 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1462 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1463 irg_ident, irg_ident);
1465 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1466 ir_node * node = arr[i];
1468 dump_ir_data_edges(node);
1469 if (is_Block(node)) {
1470 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1472 dump_ir_block_edge(node);
1473 dump_ir_data_edges(node);
1480 /* Close the vcg information for the irg */
1481 xfprintf(F, "}\n\n");