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"
35 /* Attributes of nodes */
36 #define DEFAULT_NODE_ATTR ""
37 #define DEFAULT_TYPE_ATTRIBUTE ""
39 /* Attributes of edges between Firm nodes */
40 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
41 #define CF_EDGE_ATTR "color: red"
42 #define MEM_EDGE_ATTR "color: blue"
43 #define DOMINATOR_EDGE_ATTR "color: red"
45 /* Attributes of edges between Firm nodes and type/entity nodes */
46 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
48 /* Attributes of edges in type/entity graphs. */
49 #define TYPE_METH_NODE_ATTR "color: lightyellow"
50 #define TYPE_CLASS_NODE_ATTR "color: green"
51 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
52 #define ENTITY_NODE_ATTR "color: yellow"
53 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
54 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
55 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
56 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
57 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: blue"
58 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
59 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
60 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
61 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
62 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
63 #define ENT_VALUE_EDGE_ATTR "label: \"value "
64 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
65 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
68 #if DEBUG_libfirm && NODEID_AS_LABEL
69 #define PRINT_NODEID(X) fprintf(F, "%d", get_irn_node_nr(X))
71 #define PRINT_NODEID(X) fprintf(F, "%p", X)
74 /* A suffix to manipulate the file name. */
75 char *dump_file_suffix = NULL;
80 /* A compiler option to turn off edge labels */
82 /* A compiler option to turn off dumping values of constant entities */
83 int const_entities = 1;
84 /* A compiler option to dump the keep alive edges */
85 int dump_keepalive = 0;
86 /* A compiler option to dump the out edges in dump_ir_graph */
87 int dump_out_edge_flag = 0;
88 int dump_dominator_information_flag = 0;
90 /* A global variable to record output of the Bad node. */
94 void dump_ir_blocks_nodes (ir_node *n, void *env);
95 void dump_whole_node (ir_node *n, void* env);
97 /*******************************************************************/
98 /* routines to dump information about a single node */
99 /*******************************************************************/
104 dump_node_opcode (ir_node *n)
108 if (n->op->code == iro_Const) {
109 xfprintf (F, "%v", n->attr.con);
112 } else if (n->op->code == iro_SymConst) {
113 if (get_SymConst_kind(n) == linkage_ptr_info) {
114 /* don't use get_SymConst_ptr_info as it mangles the name. */
115 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
117 assert(get_kind(get_SymConst_type(n)) == k_type);
118 assert(get_type_ident(get_SymConst_type(n)));
119 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
120 if (get_SymConst_kind == type_tag)
123 xfprintf (F, "size");
127 xfprintf (F, "%I", get_irn_opident(n));
132 dump_node_mode (ir_node *n)
134 switch (n->op->code) {
151 xfprintf (F, "%I", get_mode_ident(n->mode));
158 dump_node_nodeattr (ir_node *n)
160 switch (n->op->code) {
162 if (n->in[1]->op->code == iro_Cmp) {
163 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
165 xfprintf (F, "%ld", n->attr.proj);
169 assert(get_kind(get_Sel_entity(n)) == k_entity);
170 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
177 dump_node_vcgattr (ir_node *n)
179 switch (n->op->code) {
182 xfprintf (F, "color: blue");
185 xfprintf (F, "color: lightyellow");
188 xfprintf (F, "color: green");
193 xfprintf (F, "color: yellow");
196 xfprintf (F, DEFAULT_NODE_ATTR);
201 dump_node (ir_node *n) {
204 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
209 dump_node_nodeattr(n);
211 xfprintf (F, " %ld", get_irn_node_nr(n));
214 dump_node_vcgattr(n);
219 dump_ir_node (ir_node *n)
222 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
224 switch (n->op->code) { /* node label */
226 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
227 xfprintf (F, DEFAULT_NODE_ATTR);
230 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
231 xfprintf (F, DEFAULT_NODE_ATTR);
234 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
235 xfprintf (F, DEFAULT_NODE_ATTR);
238 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
239 if (get_irn_modecode(n) == irm_M)
240 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
242 xfprintf (F, DEFAULT_NODE_ATTR);
245 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
246 xfprintf (F, DEFAULT_NODE_ATTR);
249 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
250 xfprintf (F, DEFAULT_NODE_ATTR);
253 if (n->in[1]->op->code == iro_Cmp) {
254 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
255 get_pnc_string(n->attr.proj));
257 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
259 xfprintf (F, DEFAULT_NODE_ATTR);
262 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
263 xfprintf (F, DEFAULT_NODE_ATTR);
266 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
267 xfprintf (F, DEFAULT_NODE_ATTR);
270 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
271 xfprintf (F, DEFAULT_NODE_ATTR);
274 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
275 xfprintf (F, DEFAULT_NODE_ATTR);
278 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
279 xfprintf (F, DEFAULT_NODE_ATTR);
282 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
283 xfprintf (F, DEFAULT_NODE_ATTR);
286 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
287 xfprintf (F, DEFAULT_NODE_ATTR);
290 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
291 xfprintf (F, DEFAULT_NODE_ATTR);
294 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
295 xfprintf (F, DEFAULT_NODE_ATTR);
298 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
299 xfprintf (F, DEFAULT_NODE_ATTR);
302 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
303 xfprintf (F, DEFAULT_NODE_ATTR);
306 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
307 xfprintf (F, DEFAULT_NODE_ATTR);
310 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
311 xfprintf (F, DEFAULT_NODE_ATTR);
314 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
315 xfprintf (F, DEFAULT_NODE_ATTR);
318 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
319 xfprintf (F, DEFAULT_NODE_ATTR);
322 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
323 xfprintf (F, DEFAULT_NODE_ATTR);
326 xfprintf (F, "\"%I\"", get_irn_opident(n));
327 xfprintf (F, DEFAULT_NODE_ATTR);
330 xfprintf (F, "\"%I\"", get_irn_opident(n));
331 xfprintf (F, DEFAULT_NODE_ATTR);
334 xfprintf (F, "\"%I\"", get_irn_opident(n));
335 xfprintf (F, DEFAULT_NODE_ATTR);
338 xfprintf (F, "\"%I\"", get_irn_opident(n));
339 xfprintf (F, DEFAULT_NODE_ATTR);
342 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
343 xfprintf (F, DEFAULT_NODE_ATTR);
347 xfprintf (F, "\"%R\"", n);
348 xfprintf (F, DEFAULT_NODE_ATTR);
351 xfprintf (F, "\"%I\" ", get_irn_opident(n));
352 xfprintf (F, DEFAULT_NODE_ATTR);
355 assert(get_kind(get_Sel_entity(n)) == k_entity);
356 xfprintf (F, "\"%I ", get_irn_opident(n));
357 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
358 xfprintf (F, DEFAULT_NODE_ATTR);
361 assert(get_kind(get_SymConst_type(n)) == k_type);
362 assert(get_type_ident(get_SymConst_type(n)));
363 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
364 switch (n->attr.i.num){
366 xfprintf (F, "tag\" ");
369 xfprintf (F, "size\" ");
375 xfprintf (F, DEFAULT_NODE_ATTR);
378 xfprintf (F, "\"%I\" ", get_irn_opident(n));
379 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
382 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
383 xfprintf (F, DEFAULT_NODE_ATTR);
386 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
388 xfprintf (F, "}\n"); /* footer */
392 /* dump the edge to the block this node belongs to */
394 dump_ir_block_edge(ir_node *n) {
395 if (is_no_Block(n)) {
396 xfprintf (F, "edge: { sourcename: \"");
398 xfprintf (F, "\" targetname: \"");
399 PRINT_NODEID(get_nodes_Block(n));
400 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
404 void print_edge_vcgattr(ir_node *from, int to) {
407 switch (get_irn_opcode(from)) {
409 xfprintf (F, CF_EDGE_ATTR);
411 case iro_Start: break;
414 if (get_irn_mode(get_End_keepalive(from, to)) == mode_R)
415 xfprintf (F, CF_EDGE_ATTR);
416 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
417 xfprintf (F, MEM_EDGE_ATTR);
421 case iro_Cond: break;
424 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
426 case iro_Const: break;
427 case iro_SymConst:break;
430 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
434 case iro_Minus: break;
440 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
448 case iro_Shrs: break;
451 case iro_Conv: break;
453 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
459 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
462 xfprintf (F, MEM_EDGE_ATTR);
464 case iro_Tuple: break;
466 switch (get_irn_modecode(from)) {
468 xfprintf (F, CF_EDGE_ATTR);
471 xfprintf (F, MEM_EDGE_ATTR);
482 /* dump edges to our inputs */
484 dump_ir_data_edges(ir_node *n) {
487 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
490 for (i = 0; i < get_irn_arity(n); i++) {
491 assert(get_irn_n(n, i));
492 fprintf (F, "edge: {sourcename: \"");
494 fprintf (F, "\" targetname: \"");
495 PRINT_NODEID(get_irn_n(n, i));
497 fprintf (F, " label: \"%d\" ", i);
498 print_edge_vcgattr(n, i);
505 dump_out_edge (ir_node *n, void* env) {
507 for (i = 0; i < get_irn_n_outs(n); i++) {
508 assert(get_irn_out(n, i));
509 fprintf (F, "edge: {sourcename: \"");
511 fprintf (F, "\" targetname: \"");
512 PRINT_NODEID(get_irn_out(n, i));
513 fprintf (F, "\" color: red linestyle: dashed");
519 /* dumps the edges between nodes and their type or entity attributes. */
520 void dump_node2type_edges (ir_node *n, void *env)
524 switch (get_irn_opcode(n)) {
526 /* @@@ some consts have an entity */
529 if ( (get_SymConst_kind(n) == type_tag)
530 || (get_SymConst_kind(n) == size)) {
531 xfprintf (F, "edge: { sourcename: \"");
533 fprintf (F, "\" targetname: \"%p\" "
534 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
538 xfprintf (F, "edge: { sourcename: \"");
540 fprintf (F, "\" targetname: \"%p\" "
541 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
544 xfprintf (F, "edge: { sourcename: \"");
546 fprintf (F, "\" targetname: \"%p\" "
547 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
550 xfprintf (F, "edge: { sourcename: \"");
552 fprintf (F, "\" targetname: \"%p\" "
553 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
556 xfprintf (F, "edge: { sourcename: \"");
558 fprintf (F, "\" targetname: \"%p\" "
559 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
567 void dump_const_expression(ir_node *value) {
568 ir_graph *rem = current_ir_graph;
569 current_ir_graph = get_const_code_irg();
570 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
571 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
572 current_ir_graph = rem;
576 void print_type_info(type *tp) {
577 if (get_type_state(tp) == layout_undefined) {
578 xfprintf(F, "state: layout_undefined\n");
580 xfprintf(F, "state: layout_fixed,\n");
582 if (get_type_mode(tp))
583 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
584 xfprintf(F, "size: %dB,\n", get_type_size(tp));
588 void print_typespecific_info(type *tp) {
589 switch (get_type_tpop_code(tp)) {
592 if(existent == get_class_peculiarity(tp))
593 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
595 xfprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
599 xfprintf (F, " " TYPE_METH_NODE_ATTR);
610 case tpo_enumeration:
623 void print_type_node(type *tp) {
624 xfprintf (F, "node: {title: \"%p\" ", tp);
625 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
626 xfprintf (F, "info1: \"");
629 print_typespecific_info(tp);
633 /* dumps a type or entity and it's edges. */
635 dump_type_info (type_or_ent *tore, void *env) {
636 int i = 0; /* to shutup gcc */
638 /* dump this type or entity */
640 switch (get_kind(tore)) {
643 entity *ent = (entity *)tore;
646 xfprintf (F, "node: {title: \"%p\" ", tore);
647 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
648 xfprintf (F, "label: ");
649 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
650 if(dynamic_allocated == get_entity_allocation(ent))
651 xfprintf (F, " info1:\"dynamic allocated\n");
653 xfprintf (F, " info1:\"static allocated\n");
654 switch (get_entity_visibility(ent)) {
655 case local: fprintf (F, "local\n"); break;
656 case external_visible: fprintf (F, "external_visible\n"); break;
657 case external_allocated: fprintf (F, "external_allocate\n");break;
659 switch (get_entity_variability(ent)) {
660 case uninitialized: fprintf (F, "uninitialized");break;
661 case initialized: fprintf (F, "initialized"); break;
662 case part_constant: fprintf (F, "part_constant");break;
663 case constant: fprintf (F, "constant"); break;
665 if (is_method_type(get_entity_type(ent)))
666 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
667 xfprintf(F, "\"}\n");
669 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
670 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
671 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
672 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
673 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
674 if(is_class_type(get_entity_owner(ent))) {
675 for(i = 0; i < get_entity_n_overwrites(ent); i++)
676 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
677 ENT_OVERWRITES_EDGE_ATTR "}\n",
678 ent, get_entity_overwrites(ent, i));
680 /* attached subgraphs */
681 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
682 if (is_atomic_entity(ent)) {
683 value = get_atomic_ent_value(ent);
684 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
686 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
687 dump_const_expression(value);
689 if (is_compound_entity(ent)) {
690 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
691 value = get_compound_ent_value(ent, i);
692 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
694 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
695 dump_const_expression(value);
696 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
697 ENT_CORR_EDGE_ATTR "}\n", ent,
698 get_compound_ent_value_member(ent, i), i);
705 type *tp = (type *)tore;
707 /* and now the edges */
708 switch (get_type_tpop_code(tp)) {
711 for (i=0; i < get_class_n_supertype(tp); i++)
712 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
713 TYPE_SUPER_EDGE_ATTR "}\n",
714 tp, get_class_supertype(tp, i));
715 for (i=0; i < get_class_n_member(tp); i++)
716 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
717 TYPE_MEMBER_EDGE_ATTR "}\n",
718 tp, get_class_member(tp, i));
722 for (i=0; i < get_struct_n_member(tp); i++)
723 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
724 TYPE_MEMBER_EDGE_ATTR "}\n",
725 tp, get_struct_member(tp, i));
729 for (i = 0; i < get_method_n_params(tp); i++)
730 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
731 METH_PAR_EDGE_ATTR "}\n",
732 tp, get_method_param_type(tp, i), i);
733 for (i = 0; i < get_method_n_res(tp); i++)
734 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
735 METH_RES_EDGE_ATTR "}\n",
736 tp, get_method_res_type(tp, i), i);
740 for (i = 0; i < get_union_n_members(tp); i++)
741 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
742 "label: \"\"f" UNION_EDGE_ATTR "}\n",
743 tp, get_union_member(tp, i));
747 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
748 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
749 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
750 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
752 case tpo_enumeration:
757 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
758 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
759 get_pointer_points_to_type(tp), i);
767 break; /* case k_type */
770 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
772 } /* switch kind_or_entity */
775 /************************************************************************/
776 /* open and close vcg file */
777 /************************************************************************/
779 void vcg_open (ir_graph *irg, char *suffix) {
780 char *fname; /* filename to put the vcg information in */
787 /** open file for vcg graph */
788 ent = get_irg_ent(irg);
789 id = ent->ld_name ? ent->ld_name : ent->name;
790 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
791 len = id_to_strlen (id);
793 if (dump_file_suffix)
794 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
796 fname = malloc (len + 5 + strlen(suffix));
797 strncpy (fname, cp, len); /* copy the filename */
799 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
800 strcat (fname, suffix); /* append file suffix */
801 strcat (fname, ".vcg"); /* append the .vcg suffix */
802 F = fopen (fname, "w"); /* open file for writing */
804 panic ("cannot open %s for writing (%m)", fname); /* not reached */
808 strcpy(label, "yes");
810 strcpy (label, "no");
815 "graph: { title: \"ir graph of %s\"\n"
816 "display_edge_labels: %s\n"
817 "layoutalgorithm: mindepth\n"
818 "manhattan_edges: yes\n"
820 "orientation: bottom_to_top\n"
821 "classname 1: \"Data\"\n"
822 "classname 2: \"Block\"\n"
823 "classname 3: \"Entity type\""
824 "classname 4: \"Entity owner\""
825 "classname 5: \"Method Param\""
826 "classname 6: \"Method Res\""
827 "classname 7: \"Super\""
828 "classname 8: \"Union\""
829 "classname 9: \"Points-to\""
830 "classname 10: \"Array Element Type\""
831 "classname 11: \"Overwrites\""
832 "classname 12: \"Member\""
835 xfprintf (F, "\n"); /* a separator */
838 void vcg_open_name (const char *name) {
839 char *fname; /* filename to put the vcg information in */
843 /** open file for vcg graph */
845 fname = malloc (len + 5);
846 strcpy (fname, name); /* copy the filename */
847 strcat (fname, ".vcg"); /* append the .vcg suffix */
848 F = fopen (fname, "w"); /* open file for writing */
850 panic ("cannot open %s for writing (%m)", fname); /* not reached */
854 strcpy(label, "yes");
856 strcpy (label, "no");
861 "graph: { title: \"ir graph of %s\"\n"
862 "display_edge_labels: %s\n"
863 "layoutalgorithm: mindepth\n"
864 "manhattan_edges: yes\n"
866 "orientation: bottom_to_top\n"
867 "classname 1: \"Data\"\n"
868 "classname 2: \"Block\"\n"
869 "classname 3: \"Entity type\"\n"
870 "classname 4: \"Entity owner\"\n"
871 "classname 5: \"Method Param\"\n"
872 "classname 6: \"Method Res\"\n"
873 "classname 7: \"Super\"\n"
874 "classname 8: \"Union\"\n"
875 "classname 9: \"Points-to\"\n"
876 "classname 10: \"Array Element Type\"\n"
877 "classname 11: \"Overwrites\"\n"
878 "classname 12: \"Member\"\n"
881 xfprintf (F, "\n"); /* a separator */
886 xfprintf (F, "}\n"); /* print footer */
887 fclose (F); /* close vcg file */
890 /************************************************************************/
891 /* routines to dump a graph, blocks as conventional nodes. */
892 /************************************************************************/
895 dump_whole_node (ir_node *n, void* env) {
897 if (!node_floats(n)) dump_ir_block_edge(n);
898 dump_ir_data_edges(n);
902 dump_ir_graph (ir_graph *irg)
905 rem = current_ir_graph;
906 current_ir_graph = irg;
910 /* walk over the graph */
911 irg_walk(irg->end, dump_whole_node, NULL, NULL);
913 /* dump the out edges in a separate walk */
914 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
915 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
920 current_ir_graph = rem;
923 /***********************************************************************/
924 /* the following routines dump the nodes as attached to the blocks. */
925 /***********************************************************************/
927 int node_floats(ir_node *n) {
929 return ((get_op_pinned(get_irn_op(n)) == floats) &&
930 (get_irg_pinned(current_ir_graph) == floats));
934 dump_ir_blocks_nodes (ir_node *n, void *env) {
935 ir_node *block = (ir_node *)env;
937 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
939 dump_ir_data_edges(n);
941 if (get_irn_op(n) == op_Bad)
946 dump_ir_block (ir_node *block, void *env) {
947 ir_graph *irg = (ir_graph *)env;
949 if (get_irn_opcode(block) == iro_Block) {
951 /* This is a block. So dump the vcg information to make a block. */
952 xfprintf(F, "graph: { title: \"");
954 fprintf(F, "\" label: \"");
956 xfprintf (F, "%ld", get_irn_node_nr(block));
958 xfprintf (F, "%I", block->op->name);
960 if (exc_normal != get_Block_exc (block))
961 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
963 xfprintf(F, "\" status:clustered color:%s \n",
964 get_Block_matured (block) ? "yellow" : "red");
965 /* dump the blocks edges */
966 dump_ir_data_edges(block);
968 /* dump the nodes that go into the block */
969 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
971 /* Close the vcg information for the block */
972 xfprintf(F, "}\n\n");
978 dump_blockless_nodes (ir_node *n, void *env) {
979 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
981 dump_ir_data_edges(n);
982 dump_ir_block_edge(n);
983 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
986 if (node_floats(n)) {
988 dump_ir_data_edges(n);
989 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
993 void dump_ir_block_graph_2 (ir_graph *irg)
996 /* walk over the blocks in the graph */
997 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
999 /* dump all nodes that are not in a Block */
1000 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1002 /* dump the Bad node */
1004 dump_node(get_irg_bad(irg));
1008 dump_ir_block_graph (ir_graph *irg)
1011 rem = current_ir_graph;
1012 current_ir_graph = irg;
1016 dump_ir_block_graph_2 (irg);
1019 current_ir_graph = rem;
1023 /***********************************************************************/
1024 /* the following routines dump a control flow graph */
1025 /***********************************************************************/
1029 dump_block_to_cfg (ir_node *block, void *env) {
1033 if (get_irn_opcode(block) == iro_Block) {
1034 /* This is a block. Dump a node for the block. */
1035 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1036 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1038 if (exc_normal != get_Block_exc (block))
1039 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1041 xfprintf (F, "\" ");
1042 if (dump_dominator_information_flag)
1043 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1044 xfprintf (F, "}\n");
1045 /* Dump the edges */
1046 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1047 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1048 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1049 xfprintf (F, "edge: { sourcename: \"");
1050 PRINT_NODEID(block);
1051 fprintf (F, "\" targetname: \"");
1053 fprintf (F, "\" }\n");
1056 /* Dump dominator edge */
1057 if (dump_dominator_information_flag && get_Block_idom(block)) {
1058 pred = get_Block_idom(block);
1059 xfprintf (F, "edge: { sourcename: \"");
1060 PRINT_NODEID(block);
1061 fprintf (F, "\" targetname: \"");
1063 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1069 dump_cfg (ir_graph *irg)
1071 ir_graph *rem = current_ir_graph;
1072 int ddif = dump_dominator_information_flag;
1073 current_ir_graph = irg;
1074 vcg_open (irg, "-cfg");
1076 if (get_irg_dom_state(irg) != dom_consistent)
1077 dump_dominator_information_flag = 0;
1079 /* walk over the blocks in the graph */
1080 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1081 dump_ir_node (irg->bad);
1083 dump_dominator_information_flag = ddif;
1085 current_ir_graph = rem;
1089 /***********************************************************************/
1090 /* the following routine dumps all type information reachable from an */
1092 /***********************************************************************/
1096 dump_type_graph (ir_graph *irg)
1099 rem = current_ir_graph;
1100 current_ir_graph = irg;
1102 vcg_open (irg, "-type");
1104 /* walk over the blocks in the graph */
1105 type_walk_irg(irg, dump_type_info, NULL, NULL);
1106 /* The walker for the const code can be called several times for the
1107 same (sub) experssion. So that no nodes are dumped several times
1108 we decrease the visited flag of the corresponding graph after each
1109 walk. So now increase it finally. */
1110 inc_irg_visited(get_const_code_irg());
1113 current_ir_graph = rem;
1116 /***********************************************************************/
1117 /* the following routine dumps all type information */
1118 /***********************************************************************/
1122 dump_all_types (void)
1124 vcg_open_name ("All_types");
1125 type_walk(dump_type_info, NULL, NULL);
1126 inc_irg_visited(get_const_code_irg());
1130 /***********************************************************************/
1131 /* dumps a graph with type information */
1132 /***********************************************************************/
1136 dump_ir_graph_w_types (ir_graph *irg)
1139 rem = current_ir_graph;
1140 current_ir_graph = irg;
1142 vcg_open (irg, "-all");
1144 /* dump common ir graph */
1145 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1146 /* dump type info */
1147 type_walk_irg(irg, dump_type_info, NULL, NULL);
1148 inc_irg_visited(get_const_code_irg());
1149 /* dump edges from graph to type info */
1150 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1153 current_ir_graph = rem;
1157 dump_ir_block_graph_w_types (ir_graph *irg)
1160 rem = current_ir_graph;
1161 current_ir_graph = irg;
1163 vcg_open (irg, "-all");
1165 /* dump common blocked ir graph */
1166 dump_ir_block_graph_2(irg);
1167 /* dump type info */
1168 type_walk_irg(irg, dump_type_info, NULL, NULL);
1169 inc_irg_visited(get_const_code_irg());
1170 /* dump edges from graph to type info */
1171 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1174 current_ir_graph = rem;
1177 /***********************************************************************/
1178 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1180 /* dump_ir_block_graph */
1182 /* dump_type_graph */
1183 /* dump_ir_graph_w_types */
1184 /***********************************************************************/
1185 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1187 for (i=0; i < get_irp_n_irgs(); i++) {
1188 dump_graph(get_irp_irg(i));
1193 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1194 abort with a segmentation fault. */
1195 void turn_off_edge_labels() {
1199 void turn_off_constant_entity_values() {
1203 void dump_keepalive_edges() {
1207 void dump_out_edges() {
1208 dump_out_edge_flag = 1;
1211 void dump_dominator_information() {
1212 dump_dominator_information_flag = 1;