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"
33 /* Attributes of nodes */
34 #define DEFAULT_NODE_ATTR ""
35 #define DEFAULT_TYPE_ATTRIBUTE ""
37 /* Attributes of edges between Firm nodes */
38 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
39 #define CF_EDGE_ATTR "color: red"
40 #define MEM_EDGE_ATTR "color: blue"
41 #define DOMINATOR_EDGE_ATTR "color: red"
43 /* Attributes of edges between Firm nodes and type/entity nodes */
44 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
46 /* Attributes of edges in type/entity graphs. */
47 #define TYPE_METH_NODE_ATTR "color: lightyellow"
48 #define TYPE_CLASS_NODE_ATTR "color: green"
49 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
50 #define ENTITY_NODE_ATTR "color: yellow"
51 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
52 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
53 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
54 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
55 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: blue"
56 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
57 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
58 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
59 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
60 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
61 #define ENT_VALUE_EDGE_ATTR "label: \"value "
62 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
63 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
66 #if DEBUG_libfirm && NODEID_AS_LABEL
67 #define PRINT_NODEID(X) fprintf(F, "%d", get_irn_node_nr(X))
69 #define PRINT_NODEID(X) fprintf(F, "%p", X)
72 /* A suffix to manipulate the file name. */
73 char *dump_file_suffix = NULL;
78 /* A compiler option to turn off edge labels */
80 /* A compiler option to turn off dumping values of constant entities */
81 int const_entities = 1;
82 /* A compiler option to dump the keep alive edges */
83 int dump_keepalive = 0;
84 /* A compiler option to dump the out edges in dump_ir_graph */
85 int dump_out_edge_flag = 0;
86 int dump_dominator_information_flag = 0;
88 /* A global variable to record output of the Bad node. */
92 void dump_ir_blocks_nodes (ir_node *n, void *env);
93 void dump_whole_node (ir_node *n, void* env);
95 /*******************************************************************/
96 /* routines to dump information about a single node */
97 /*******************************************************************/
102 dump_node_opcode (ir_node *n)
106 if (n->op->code == iro_Const) {
107 xfprintf (F, "%v", n->attr.con);
110 } else if (n->op->code == iro_SymConst) {
111 if (get_SymConst_kind(n) == linkage_ptr_info) {
112 /* don't use get_SymConst_ptr_info as it mangles the name. */
113 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
115 assert(get_kind(get_SymConst_type(n)) == k_type);
116 assert(get_type_ident(get_SymConst_type(n)));
117 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
118 if (get_SymConst_kind == type_tag)
121 xfprintf (F, "size");
125 xfprintf (F, "%I", get_irn_opident(n));
130 dump_node_mode (ir_node *n)
132 switch (n->op->code) {
149 xfprintf (F, "%I", get_mode_ident(n->mode));
156 dump_node_nodeattr (ir_node *n)
158 switch (n->op->code) {
160 if (n->in[1]->op->code == iro_Cmp) {
161 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
163 xfprintf (F, "%ld", n->attr.proj);
167 assert(get_kind(get_Sel_entity(n)) == k_entity);
168 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
175 dump_node_vcgattr (ir_node *n)
177 switch (n->op->code) {
180 xfprintf (F, "color: blue");
183 xfprintf (F, "color: lightyellow");
186 xfprintf (F, "color: green");
191 xfprintf (F, "color: yellow");
194 xfprintf (F, DEFAULT_NODE_ATTR);
199 dump_node (ir_node *n) {
202 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
207 dump_node_nodeattr(n);
209 xfprintf (F, " %ld", get_irn_node_nr(n));
212 dump_node_vcgattr(n);
217 dump_ir_node (ir_node *n)
220 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
222 switch (n->op->code) { /* node label */
224 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
225 xfprintf (F, DEFAULT_NODE_ATTR);
228 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
229 xfprintf (F, DEFAULT_NODE_ATTR);
232 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
233 xfprintf (F, DEFAULT_NODE_ATTR);
236 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
237 if (get_irn_modecode(n) == irm_M)
238 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
240 xfprintf (F, DEFAULT_NODE_ATTR);
243 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
244 xfprintf (F, DEFAULT_NODE_ATTR);
247 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
248 xfprintf (F, DEFAULT_NODE_ATTR);
251 if (n->in[1]->op->code == iro_Cmp) {
252 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
253 get_pnc_string(n->attr.proj));
255 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
257 xfprintf (F, DEFAULT_NODE_ATTR);
260 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
261 xfprintf (F, DEFAULT_NODE_ATTR);
264 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
265 xfprintf (F, DEFAULT_NODE_ATTR);
268 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
269 xfprintf (F, DEFAULT_NODE_ATTR);
272 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
273 xfprintf (F, DEFAULT_NODE_ATTR);
276 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
277 xfprintf (F, DEFAULT_NODE_ATTR);
280 xfprintf (F, "\"%I%I\"", get_irn_opident(n), 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 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
289 xfprintf (F, DEFAULT_NODE_ATTR);
292 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
293 xfprintf (F, DEFAULT_NODE_ATTR);
296 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
297 xfprintf (F, DEFAULT_NODE_ATTR);
300 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
301 xfprintf (F, DEFAULT_NODE_ATTR);
304 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
305 xfprintf (F, DEFAULT_NODE_ATTR);
308 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
309 xfprintf (F, DEFAULT_NODE_ATTR);
312 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
313 xfprintf (F, DEFAULT_NODE_ATTR);
316 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
317 xfprintf (F, DEFAULT_NODE_ATTR);
320 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
321 xfprintf (F, DEFAULT_NODE_ATTR);
324 xfprintf (F, "\"%I\"", get_irn_opident(n));
325 xfprintf (F, DEFAULT_NODE_ATTR);
328 xfprintf (F, "\"%I\"", get_irn_opident(n));
329 xfprintf (F, DEFAULT_NODE_ATTR);
332 xfprintf (F, "\"%I\"", get_irn_opident(n));
333 xfprintf (F, DEFAULT_NODE_ATTR);
336 xfprintf (F, "\"%I\"", get_irn_opident(n));
337 xfprintf (F, DEFAULT_NODE_ATTR);
340 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
341 xfprintf (F, DEFAULT_NODE_ATTR);
345 xfprintf (F, "\"%R\"", n);
346 xfprintf (F, DEFAULT_NODE_ATTR);
349 xfprintf (F, "\"%I\" ", get_irn_opident(n));
350 xfprintf (F, DEFAULT_NODE_ATTR);
353 assert(get_kind(get_Sel_entity(n)) == k_entity);
354 xfprintf (F, "\"%I ", get_irn_opident(n));
355 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
356 xfprintf (F, DEFAULT_NODE_ATTR);
359 assert(get_kind(get_SymConst_type(n)) == k_type);
360 assert(get_type_ident(get_SymConst_type(n)));
361 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
362 switch (n->attr.i.num){
364 xfprintf (F, "tag\" ");
367 xfprintf (F, "size\" ");
373 xfprintf (F, DEFAULT_NODE_ATTR);
376 xfprintf (F, "\"%I\" ", get_irn_opident(n));
377 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
380 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
381 xfprintf (F, DEFAULT_NODE_ATTR);
384 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
386 xfprintf (F, "}\n"); /* footer */
390 /* dump the edge to the block this node belongs to */
392 dump_ir_block_edge(ir_node *n) {
393 if (is_no_Block(n)) {
394 xfprintf (F, "edge: { sourcename: \"");
396 xfprintf (F, "\" targetname: \"");
397 PRINT_NODEID(get_nodes_Block(n));
398 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
402 void print_edge_vcgattr(ir_node *from, int to) {
405 switch (get_irn_opcode(from)) {
407 xfprintf (F, CF_EDGE_ATTR);
409 case iro_Start: break;
412 if (get_irn_mode(get_End_keepalive(from, to)) == mode_R)
413 xfprintf (F, CF_EDGE_ATTR);
414 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
415 xfprintf (F, MEM_EDGE_ATTR);
419 case iro_Cond: break;
422 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
424 case iro_Const: break;
425 case iro_SymConst:break;
428 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
432 case iro_Minus: break;
438 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
446 case iro_Shrs: break;
449 case iro_Conv: break;
451 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
457 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
460 xfprintf (F, MEM_EDGE_ATTR);
462 case iro_Tuple: break;
464 switch (get_irn_modecode(from)) {
466 xfprintf (F, CF_EDGE_ATTR);
469 xfprintf (F, MEM_EDGE_ATTR);
480 /* dump edges to our inputs */
482 dump_ir_data_edges(ir_node *n) {
485 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
488 for (i = 0; i < get_irn_arity(n); i++) {
489 assert(get_irn_n(n, i));
490 fprintf (F, "edge: {sourcename: \"");
492 fprintf (F, "\" targetname: \"");
493 PRINT_NODEID(get_irn_n(n, i));
495 fprintf (F, " label: \"%d\" ", i);
496 print_edge_vcgattr(n, i);
503 dump_out_edge (ir_node *n, void* env) {
505 for (i = 0; i < get_irn_n_outs(n); i++) {
506 assert(get_irn_out(n, i));
507 fprintf (F, "edge: {sourcename: \"");
509 fprintf (F, "\" targetname: \"");
510 PRINT_NODEID(get_irn_out(n, i));
511 fprintf (F, "\" color: red linestyle: dashed");
517 /* dumps the edges between nodes and their type or entity attributes. */
518 void dump_node2type_edges (ir_node *n, void *env)
522 switch (get_irn_opcode(n)) {
524 /* @@@ some consts have an entity */
527 if ( (get_SymConst_kind(n) == type_tag)
528 || (get_SymConst_kind(n) == size)) {
529 xfprintf (F, "edge: { sourcename: \"");
531 fprintf (F, "\" targetname: \"%p\" "
532 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
536 xfprintf (F, "edge: { sourcename: \"");
538 fprintf (F, "\" targetname: \"%p\" "
539 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
542 xfprintf (F, "edge: { sourcename: \"");
544 fprintf (F, "\" targetname: \"%p\" "
545 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
548 xfprintf (F, "edge: { sourcename: \"");
550 fprintf (F, "\" targetname: \"%p\" "
551 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
554 xfprintf (F, "edge: { sourcename: \"");
556 fprintf (F, "\" targetname: \"%p\" "
557 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
565 void dump_const_expression(ir_node *value) {
566 ir_graph *rem = current_ir_graph;
567 current_ir_graph = get_const_code_irg();
568 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
569 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
570 current_ir_graph = rem;
574 void print_type_info(type *tp) {
575 if (get_type_state(tp) == layout_undefined) {
576 xfprintf(F, "state: layout_undefined\n");
578 xfprintf(F, "state: layout_fixed,\n");
580 if (get_type_mode(tp))
581 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
582 xfprintf(F, "size: %dB,\n", get_type_size(tp));
586 void print_typespecific_info(type *tp) {
587 switch (get_type_tpop_code(tp)) {
590 if(existent == get_class_peculiarity(tp))
591 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
593 xfprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
597 xfprintf (F, " " TYPE_METH_NODE_ATTR);
608 case tpo_enumeration:
621 void print_type_node(type *tp) {
622 xfprintf (F, "node: {title: \"%p\" ", tp);
623 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
624 xfprintf (F, "info1: \"");
627 print_typespecific_info(tp);
631 /* dumps a type or entity and it's edges. */
633 dump_type_info (type_or_ent *tore, void *env) {
634 int i = 0; /* to shutup gcc */
636 /* dump this type or entity */
638 switch (get_kind(tore)) {
641 entity *ent = (entity *)tore;
644 xfprintf (F, "node: {title: \"%p\" ", tore);
645 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
646 xfprintf (F, "label: ");
647 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
648 if(dynamic_allocated == get_entity_allocation(ent))
649 xfprintf (F, " info1:\"dynamic allocated\n");
651 xfprintf (F, " info1:\"static allocated\n");
652 switch (get_entity_visibility(ent)) {
653 case local: fprintf (F, "local\n"); break;
654 case external_visible: fprintf (F, "external_visible\n"); break;
655 case external_allocated: fprintf (F, "external_allocate\n");break;
657 switch (get_entity_variability(ent)) {
658 case uninitialized: fprintf (F, "uninitialized");break;
659 case initialized: fprintf (F, "initialized"); break;
660 case part_constant: fprintf (F, "part_constant");break;
661 case constant: fprintf (F, "constant"); break;
663 if (is_method_type(get_entity_type(ent)))
664 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
665 xfprintf(F, "\"}\n");
667 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
668 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
669 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
670 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
671 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
672 if(is_class_type(get_entity_owner(ent))) {
673 for(i = 0; i < get_entity_n_overwrites(ent); i++)
674 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
675 ENT_OVERWRITES_EDGE_ATTR "}\n",
676 ent, get_entity_overwrites(ent, i));
678 /* attached subgraphs */
679 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
680 if (is_atomic_entity(ent)) {
681 value = get_atomic_ent_value(ent);
682 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
684 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
685 dump_const_expression(value);
687 if (is_compound_entity(ent)) {
688 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
689 value = get_compound_ent_value(ent, i);
690 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
692 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
693 dump_const_expression(value);
694 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
695 ENT_CORR_EDGE_ATTR "}\n", ent,
696 get_compound_ent_value_member(ent, i), i);
703 type *tp = (type *)tore;
705 /* and now the edges */
706 switch (get_type_tpop_code(tp)) {
709 for (i=0; i < get_class_n_supertype(tp); i++)
710 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
711 TYPE_SUPER_EDGE_ATTR "}\n",
712 tp, get_class_supertype(tp, i));
713 for (i=0; i < get_class_n_member(tp); i++)
714 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
715 TYPE_MEMBER_EDGE_ATTR "}\n",
716 tp, get_class_member(tp, i));
720 for (i=0; i < get_struct_n_member(tp); i++)
721 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
722 TYPE_MEMBER_EDGE_ATTR "}\n",
723 tp, get_struct_member(tp, i));
727 for (i = 0; i < get_method_n_params(tp); i++)
728 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
729 METH_PAR_EDGE_ATTR "}\n",
730 tp, get_method_param_type(tp, i), i);
731 for (i = 0; i < get_method_n_res(tp); i++)
732 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
733 METH_RES_EDGE_ATTR "}\n",
734 tp, get_method_res_type(tp, i), i);
738 for (i = 0; i < get_union_n_members(tp); i++)
739 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
740 "label: \"\"f" UNION_EDGE_ATTR "}\n",
741 tp, get_union_member(tp, i));
745 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
746 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
747 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
748 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
750 case tpo_enumeration:
755 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
756 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
757 get_pointer_points_to_type(tp), i);
765 break; /* case k_type */
768 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
770 } /* switch kind_or_entity */
773 /************************************************************************/
774 /* open and close vcg file */
775 /************************************************************************/
777 void vcg_open (ir_graph *irg, char *suffix) {
778 char *fname; /* filename to put the vcg information in */
785 /** open file for vcg graph */
786 ent = get_irg_ent(irg);
787 id = ent->ld_name ? ent->ld_name : ent->name;
788 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
789 len = id_to_strlen (id);
791 if (dump_file_suffix)
792 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
794 fname = malloc (len + 5 + strlen(suffix));
795 strncpy (fname, cp, len); /* copy the filename */
797 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
798 strcat (fname, suffix); /* append file suffix */
799 strcat (fname, ".vcg"); /* append the .vcg suffix */
800 F = fopen (fname, "w"); /* open file for writing */
802 panic ("cannot open %s for writing (%m)", fname); /* not reached */
806 strcpy(label, "yes");
808 strcpy (label, "no");
813 "graph: { title: \"ir graph of %s\"\n"
814 "display_edge_labels: %s\n"
815 "layoutalgorithm: mindepth\n"
816 "manhattan_edges: yes\n"
818 "orientation: bottom_to_top\n"
819 "classname 1: \"Data\"\n"
820 "classname 2: \"Block\"\n"
821 "classname 3: \"Entity type\""
822 "classname 4: \"Entity owner\""
823 "classname 5: \"Method Param\""
824 "classname 6: \"Method Res\""
825 "classname 7: \"Super\""
826 "classname 8: \"Union\""
827 "classname 9: \"Points-to\""
828 "classname 10: \"Array Element Type\""
829 "classname 11: \"Overwrites\""
830 "classname 12: \"Member\""
833 xfprintf (F, "\n"); /* a separator */
836 void vcg_open_name (const char *name) {
837 char *fname; /* filename to put the vcg information in */
841 /** open file for vcg graph */
843 fname = malloc (len + 5);
844 strcpy (fname, name); /* copy the filename */
845 strcat (fname, ".vcg"); /* append the .vcg suffix */
846 F = fopen (fname, "w"); /* open file for writing */
848 panic ("cannot open %s for writing (%m)", fname); /* not reached */
852 strcpy(label, "yes");
854 strcpy (label, "no");
859 "graph: { title: \"ir graph of %s\"\n"
860 "display_edge_labels: %s\n"
861 "layoutalgorithm: mindepth\n"
862 "manhattan_edges: yes\n"
864 "orientation: bottom_to_top\n"
865 "classname 1: \"Data\"\n"
866 "classname 2: \"Block\"\n"
867 "classname 3: \"Entity type\"\n"
868 "classname 4: \"Entity owner\"\n"
869 "classname 5: \"Method Param\"\n"
870 "classname 6: \"Method Res\"\n"
871 "classname 7: \"Super\"\n"
872 "classname 8: \"Union\"\n"
873 "classname 9: \"Points-to\"\n"
874 "classname 10: \"Array Element Type\"\n"
875 "classname 11: \"Overwrites\"\n"
876 "classname 12: \"Member\"\n"
879 xfprintf (F, "\n"); /* a separator */
884 xfprintf (F, "}\n"); /* print footer */
885 fclose (F); /* close vcg file */
888 /************************************************************************/
889 /* routines to dump a graph, blocks as conventional nodes. */
890 /************************************************************************/
893 dump_whole_node (ir_node *n, void* env) {
895 if (!node_floats(n)) dump_ir_block_edge(n);
896 dump_ir_data_edges(n);
900 dump_ir_graph (ir_graph *irg)
903 rem = current_ir_graph;
904 current_ir_graph = irg;
908 /* walk over the graph */
909 irg_walk(irg->end, dump_whole_node, NULL, NULL);
911 /* dump the out edges in a separate walk */
912 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
913 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
918 current_ir_graph = rem;
921 /***********************************************************************/
922 /* the following routines dump the nodes as attached to the blocks. */
923 /***********************************************************************/
925 int node_floats(ir_node *n) {
927 return ((get_op_pinned(get_irn_op(n)) == floats) &&
928 (get_irg_pinned(current_ir_graph) == floats));
932 dump_ir_blocks_nodes (ir_node *n, void *env) {
933 ir_node *block = (ir_node *)env;
935 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
937 dump_ir_data_edges(n);
939 if (get_irn_op(n) == op_Bad)
944 dump_ir_block (ir_node *block, void *env) {
945 ir_graph *irg = (ir_graph *)env;
947 if (get_irn_opcode(block) == iro_Block) {
949 /* This is a block. So dump the vcg information to make a block. */
950 xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\" label: \"");
952 xfprintf (F, "%ld", get_irn_node_nr(block));
954 xfprintf (F, "%I", block->op->name);
956 xfprintf(F, "\" status:clustered color:%s \n",
957 get_Block_matured (block) ? "yellow" : "red");
958 /* dump the blocks edges */
959 dump_ir_data_edges(block);
961 /* dump the nodes that go into the block */
962 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
964 /* Close the vcg information for the block */
965 xfprintf(F, "}\n\n");
971 dump_blockless_nodes (ir_node *n, void *env) {
972 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
974 dump_ir_data_edges(n);
975 dump_ir_block_edge(n);
976 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
979 if (node_floats(n)) {
981 dump_ir_data_edges(n);
982 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
986 void dump_ir_block_graph_2 (ir_graph *irg)
989 /* walk over the blocks in the graph */
990 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
992 /* dump all nodes that are not in a Block */
993 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
995 /* dump the Bad node */
997 dump_node(get_irg_bad(irg));
1001 dump_ir_block_graph (ir_graph *irg)
1004 rem = current_ir_graph;
1005 current_ir_graph = irg;
1009 dump_ir_block_graph_2 (irg);
1012 current_ir_graph = rem;
1016 /***********************************************************************/
1017 /* the following routines dump a control flow graph */
1018 /***********************************************************************/
1022 dump_block_to_cfg (ir_node *block, void *env) {
1026 if (get_irn_opcode(block) == iro_Block) {
1027 /* This is a block. Dump a node for the block. */
1028 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1029 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1030 xfprintf (F, "\" ");
1031 if (dump_dominator_information_flag)
1032 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1033 xfprintf (F, "}\n");
1034 /* Dump the edges */
1035 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1036 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1037 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1038 xfprintf (F, "edge: { sourcename: \"");
1039 PRINT_NODEID(block);
1040 fprintf (F, "\" targetname: \"");
1042 fprintf (F, "\" }\n");
1045 /* Dump dominator edge */
1046 if (dump_dominator_information_flag && get_Block_idom(block)) {
1047 pred = get_Block_idom(block);
1048 xfprintf (F, "edge: { sourcename: \"");
1049 PRINT_NODEID(block);
1050 fprintf (F, "\" targetname: \"");
1052 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1058 dump_cfg (ir_graph *irg)
1060 ir_graph *rem = current_ir_graph;
1061 int ddif = dump_dominator_information_flag;
1062 current_ir_graph = irg;
1063 vcg_open (irg, "-cfg");
1065 if (get_irg_dom_state(irg) != dom_consistent)
1066 dump_dominator_information_flag = 0;
1068 /* walk over the blocks in the graph */
1069 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1070 dump_ir_node (irg->bad);
1072 dump_dominator_information_flag = ddif;
1074 current_ir_graph = rem;
1078 /***********************************************************************/
1079 /* the following routine dumps all type information reachable from an */
1081 /***********************************************************************/
1085 dump_type_graph (ir_graph *irg)
1088 rem = current_ir_graph;
1089 current_ir_graph = irg;
1091 vcg_open (irg, "-type");
1093 /* walk over the blocks in the graph */
1094 type_walk_irg(irg, dump_type_info, NULL, NULL);
1095 /* The walker for the const code can be called several times for the
1096 same (sub) experssion. So that no nodes are dumped several times
1097 we decrease the visited flag of the corresponding graph after each
1098 walk. So now increase it finally. */
1099 inc_irg_visited(get_const_code_irg());
1102 current_ir_graph = rem;
1105 /***********************************************************************/
1106 /* the following routine dumps all type information */
1107 /***********************************************************************/
1111 dump_all_types (void)
1113 vcg_open_name ("All_types");
1114 type_walk(dump_type_info, NULL, NULL);
1115 inc_irg_visited(get_const_code_irg());
1119 /***********************************************************************/
1120 /* dumps a graph with type information */
1121 /***********************************************************************/
1125 dump_ir_graph_w_types (ir_graph *irg)
1128 rem = current_ir_graph;
1129 current_ir_graph = irg;
1131 vcg_open (irg, "-all");
1133 /* dump common ir graph */
1134 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1135 /* dump type info */
1136 type_walk_irg(irg, dump_type_info, NULL, NULL);
1137 inc_irg_visited(get_const_code_irg());
1138 /* dump edges from graph to type info */
1139 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1142 current_ir_graph = rem;
1146 dump_ir_block_graph_w_types (ir_graph *irg)
1149 rem = current_ir_graph;
1150 current_ir_graph = irg;
1152 vcg_open (irg, "-all");
1154 /* dump common blocked ir graph */
1155 dump_ir_block_graph_2(irg);
1156 /* dump type info */
1157 type_walk_irg(irg, dump_type_info, NULL, NULL);
1158 inc_irg_visited(get_const_code_irg());
1159 /* dump edges from graph to type info */
1160 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1163 current_ir_graph = rem;
1166 /***********************************************************************/
1167 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1169 /* dump_ir_block_graph */
1171 /* dump_type_graph */
1172 /* dump_ir_graph_w_types */
1173 /***********************************************************************/
1174 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1176 for (i=0; i < get_irp_n_irgs(); i++) {
1177 dump_graph(get_irp_irg(i));
1182 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1183 abort with a segmentation fault. */
1184 void turn_off_edge_labels() {
1188 void turn_off_constant_entity_values() {
1192 void dump_keepalive_edges() {
1196 void dump_out_edges() {
1197 dump_out_edge_flag = 1;
1200 void dump_dominator_information() {
1201 dump_dominator_information_flag = 1;