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 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
962 xfprintf(F, "\" status:clustered color:%s \n",
963 get_Block_matured (block) ? "yellow" : "red");
964 /* dump the blocks edges */
965 dump_ir_data_edges(block);
967 /* dump the nodes that go into the block */
968 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
970 /* Close the vcg information for the block */
971 xfprintf(F, "}\n\n");
977 dump_blockless_nodes (ir_node *n, void *env) {
978 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
980 dump_ir_data_edges(n);
981 dump_ir_block_edge(n);
982 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
985 if (node_floats(n)) {
987 dump_ir_data_edges(n);
988 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
992 void dump_ir_block_graph_2 (ir_graph *irg)
995 /* walk over the blocks in the graph */
996 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
998 /* dump all nodes that are not in a Block */
999 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1001 /* dump the Bad node */
1003 dump_node(get_irg_bad(irg));
1007 dump_ir_block_graph (ir_graph *irg)
1010 rem = current_ir_graph;
1011 current_ir_graph = irg;
1015 dump_ir_block_graph_2 (irg);
1018 current_ir_graph = rem;
1022 /***********************************************************************/
1023 /* the following routines dump a control flow graph */
1024 /***********************************************************************/
1028 dump_block_to_cfg (ir_node *block, void *env) {
1032 if (get_irn_opcode(block) == iro_Block) {
1033 /* This is a block. Dump a node for the block. */
1034 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1035 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1036 xfprintf (F, "\" ");
1037 if (dump_dominator_information_flag)
1038 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1039 xfprintf (F, "}\n");
1040 /* Dump the edges */
1041 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1042 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1043 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1044 xfprintf (F, "edge: { sourcename: \"");
1045 PRINT_NODEID(block);
1046 fprintf (F, "\" targetname: \"");
1048 fprintf (F, "\" }\n");
1051 /* Dump dominator edge */
1052 if (dump_dominator_information_flag && get_Block_idom(block)) {
1053 pred = get_Block_idom(block);
1054 xfprintf (F, "edge: { sourcename: \"");
1055 PRINT_NODEID(block);
1056 fprintf (F, "\" targetname: \"");
1058 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1064 dump_cfg (ir_graph *irg)
1066 ir_graph *rem = current_ir_graph;
1067 int ddif = dump_dominator_information_flag;
1068 current_ir_graph = irg;
1069 vcg_open (irg, "-cfg");
1071 if (get_irg_dom_state(irg) != dom_consistent)
1072 dump_dominator_information_flag = 0;
1074 /* walk over the blocks in the graph */
1075 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1076 dump_ir_node (irg->bad);
1078 dump_dominator_information_flag = ddif;
1080 current_ir_graph = rem;
1084 /***********************************************************************/
1085 /* the following routine dumps all type information reachable from an */
1087 /***********************************************************************/
1091 dump_type_graph (ir_graph *irg)
1094 rem = current_ir_graph;
1095 current_ir_graph = irg;
1097 vcg_open (irg, "-type");
1099 /* walk over the blocks in the graph */
1100 type_walk_irg(irg, dump_type_info, NULL, NULL);
1101 /* The walker for the const code can be called several times for the
1102 same (sub) experssion. So that no nodes are dumped several times
1103 we decrease the visited flag of the corresponding graph after each
1104 walk. So now increase it finally. */
1105 inc_irg_visited(get_const_code_irg());
1108 current_ir_graph = rem;
1111 /***********************************************************************/
1112 /* the following routine dumps all type information */
1113 /***********************************************************************/
1117 dump_all_types (void)
1119 vcg_open_name ("All_types");
1120 type_walk(dump_type_info, NULL, NULL);
1121 inc_irg_visited(get_const_code_irg());
1125 /***********************************************************************/
1126 /* dumps a graph with type information */
1127 /***********************************************************************/
1131 dump_ir_graph_w_types (ir_graph *irg)
1134 rem = current_ir_graph;
1135 current_ir_graph = irg;
1137 vcg_open (irg, "-all");
1139 /* dump common ir graph */
1140 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1141 /* dump type info */
1142 type_walk_irg(irg, dump_type_info, NULL, NULL);
1143 inc_irg_visited(get_const_code_irg());
1144 /* dump edges from graph to type info */
1145 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1148 current_ir_graph = rem;
1152 dump_ir_block_graph_w_types (ir_graph *irg)
1155 rem = current_ir_graph;
1156 current_ir_graph = irg;
1158 vcg_open (irg, "-all");
1160 /* dump common blocked ir graph */
1161 dump_ir_block_graph_2(irg);
1162 /* dump type info */
1163 type_walk_irg(irg, dump_type_info, NULL, NULL);
1164 inc_irg_visited(get_const_code_irg());
1165 /* dump edges from graph to type info */
1166 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1169 current_ir_graph = rem;
1172 /***********************************************************************/
1173 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1175 /* dump_ir_block_graph */
1177 /* dump_type_graph */
1178 /* dump_ir_graph_w_types */
1179 /***********************************************************************/
1180 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1182 for (i=0; i < get_irp_n_irgs(); i++) {
1183 dump_graph(get_irp_irg(i));
1188 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1189 abort with a segmentation fault. */
1190 void turn_off_edge_labels() {
1194 void turn_off_constant_entity_values() {
1198 void dump_keepalive_edges() {
1202 void dump_out_edges() {
1203 dump_out_edge_flag = 1;
1206 void dump_dominator_information() {
1207 dump_dominator_information_flag = 1;