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 /* Attributes of nodes */
32 #define DEFAULT_NODE_ATTR ""
33 #define DEFAULT_TYPE_ATTRIBUTE ""
35 /* Attributes of edges between Firm nodes */
36 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
37 #define CF_EDGE_ATTR "color: red"
38 #define MEM_EDGE_ATTR "color: blue"
40 /* Attributes of edges between Firm nodes and type/entity nodes */
41 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
43 /* Attributes of edges in type/entity graphs. */
44 #define TYPE_METH_NODE_ATTR "color: lightyellow"
45 #define TYPE_CLASS_NODE_ATTR "color: green"
46 #define ENTITY_NODE_ATTR "color: yellow"
47 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
48 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
49 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
50 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
51 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: blue"
52 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
53 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
54 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
55 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
56 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
57 #define ENT_VALUE_EDGE_ATTR "label: \"value "
58 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
59 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
62 #if DEBUG_libfirm && NODEID_AS_LABEL
63 #define PRINT_NODEID(X) fprintf(F, "%d", get_irn_node_nr(X))
65 #define PRINT_NODEID(X) fprintf(F, "%p", X)
71 /* A compiler option to turn off edge labels */
73 /* A compiler option to turn off dumping values of constant entities */
74 int const_entities = 1;
75 /* A compiler option to dump the keep alive edges */
76 int dump_keepalive = 0;
77 /* A compiler option to dump the out edges in dump_ir_graph */
78 int dump_out_edge_flag = 0;
81 /* A global variable to record output of the Bad node. */
85 void dump_ir_blocks_nodes (ir_node *n, void *env);
86 void dump_whole_node (ir_node *n, void* env);
88 /*******************************************************************/
89 /* routines to dump information about a single node */
90 /*******************************************************************/
95 dump_node_opcode (ir_node *n)
99 if (n->op->code == iro_Const) {
100 xfprintf (F, "%v", n->attr.con);
103 } else if (n->op->code == iro_SymConst) {
104 if (get_SymConst_kind(n) == linkage_ptr_info) {
105 xfprintf (F, "SymC %I", get_SymConst_ptrinfo(n));
107 assert(get_kind(get_SymConst_type(n)) == k_type);
108 assert(get_type_ident(get_SymConst_type(n)));
109 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
110 if (get_SymConst_kind == type_tag)
113 xfprintf (F, "size");
117 xfprintf (F, "%I", get_irn_opident(n));
122 dump_node_mode (ir_node *n)
124 switch (n->op->code) {
141 xfprintf (F, "%I", get_mode_ident(n->mode));
148 dump_node_nodeattr (ir_node *n)
150 switch (n->op->code) {
152 if (n->in[1]->op->code == iro_Cmp) {
153 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
155 xfprintf (F, "%ld", n->attr.proj);
159 assert(get_kind(get_Sel_entity(n)) == k_entity);
160 xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
167 dump_node_vcgattr (ir_node *n)
169 switch (n->op->code) {
172 xfprintf (F, "color: blue");
175 xfprintf (F, "color: lightyellow");
178 xfprintf (F, "color: green");
183 xfprintf (F, "color: yellow");
186 xfprintf (F, DEFAULT_NODE_ATTR);
191 dump_node (ir_node *n) {
194 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
199 dump_node_nodeattr(n);
201 xfprintf (F, " %ld", get_irn_node_nr(n));
204 dump_node_vcgattr(n);
209 dump_ir_node (ir_node *n)
212 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
214 switch (n->op->code) { /* node label */
216 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
217 xfprintf (F, DEFAULT_NODE_ATTR);
220 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
221 xfprintf (F, DEFAULT_NODE_ATTR);
224 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
225 xfprintf (F, DEFAULT_NODE_ATTR);
228 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
229 if (get_irn_modecode(n) == irm_M)
230 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
232 xfprintf (F, DEFAULT_NODE_ATTR);
235 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
236 xfprintf (F, DEFAULT_NODE_ATTR);
239 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
240 xfprintf (F, DEFAULT_NODE_ATTR);
243 if (n->in[1]->op->code == iro_Cmp) {
244 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
245 get_pnc_string(n->attr.proj));
247 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
249 xfprintf (F, DEFAULT_NODE_ATTR);
252 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
253 xfprintf (F, DEFAULT_NODE_ATTR);
256 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
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\"", get_irn_opident(n));
317 xfprintf (F, DEFAULT_NODE_ATTR);
320 xfprintf (F, "\"%I\"", get_irn_opident(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%I\"", get_irn_opident(n), get_irn_modeident(n));
333 xfprintf (F, DEFAULT_NODE_ATTR);
337 xfprintf (F, "\"%R\"", n);
338 xfprintf (F, DEFAULT_NODE_ATTR);
341 xfprintf (F, "\"%I\" ", get_irn_opident(n));
342 xfprintf (F, DEFAULT_NODE_ATTR);
345 assert(get_kind(get_Sel_entity(n)) == k_entity);
346 xfprintf (F, "\"%I ", get_irn_opident(n));
347 xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
348 xfprintf (F, DEFAULT_NODE_ATTR);
351 assert(get_kind(get_SymConst_type(n)) == k_type);
352 assert(get_type_ident(get_SymConst_type(n)));
353 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
354 switch (n->attr.i.num){
356 xfprintf (F, "tag\" ");
359 xfprintf (F, "size\" ");
365 xfprintf (F, DEFAULT_NODE_ATTR);
368 xfprintf (F, "\"%I\" ", get_irn_opident(n));
369 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
372 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
373 xfprintf (F, DEFAULT_NODE_ATTR);
376 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
378 xfprintf (F, "}\n"); /* footer */
382 /* dump the edge to the block this node belongs to */
384 dump_ir_block_edge(ir_node *n) {
385 if (is_no_Block(n)) {
386 xfprintf (F, "edge: { sourcename: \"");
388 xfprintf (F, "\" targetname: \"");
389 PRINT_NODEID(get_nodes_Block(n));
390 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
394 void print_edge_vcgattr(ir_node *from, int to) {
397 switch (get_irn_opcode(from)) {
399 xfprintf (F, CF_EDGE_ATTR);
401 case iro_Start: break;
404 case iro_Cond: break;
407 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
409 case iro_Const: break;
410 case iro_SymConst:break;
413 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
417 case iro_Minus: break;
423 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
431 case iro_Shrs: break;
434 case iro_Conv: break;
436 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
442 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
445 xfprintf (F, MEM_EDGE_ATTR);
447 case iro_Tuple: break;
449 switch (get_irn_modecode(from)) {
451 xfprintf (F, CF_EDGE_ATTR);
454 xfprintf (F, MEM_EDGE_ATTR);
465 /* dump edges to our inputs */
467 dump_ir_data_edges(ir_node *n) {
470 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
473 for (i = 0; i < get_irn_arity(n); i++) {
474 assert(get_irn_n(n, i));
475 fprintf (F, "edge: {sourcename: \"");
477 fprintf (F, "\" targetname: \"");
478 PRINT_NODEID(get_irn_n(n, i));
480 fprintf (F, " label: \"%d\" ", i);
481 print_edge_vcgattr(n, i);
488 dump_out_edge (ir_node *n, void* env) {
490 for (i = 0; i < get_irn_n_outs(n); i++) {
491 assert(get_irn_out(n, i));
492 fprintf (F, "edge: {sourcename: \"");
494 fprintf (F, "\" targetname: \"");
495 PRINT_NODEID(get_irn_out(n, i));
496 fprintf (F, "\" color: red linestyle: dashed");
502 /* dumps the edges between nodes and their type or entity attributes. */
503 void dump_node2type_edges (ir_node *n, void *env)
507 switch (get_irn_opcode(n)) {
509 /* @@@ some consts have an entity */
512 if ( (get_SymConst_kind(n) == type_tag)
513 || (get_SymConst_kind(n) == size)) {
514 xfprintf (F, "edge: { sourcename: \"");
516 fprintf (F, "\" targetname: \"%p\" "
517 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
521 xfprintf (F, "edge: { sourcename: \"");
523 fprintf (F, "\" targetname: \"%p\" "
524 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
527 xfprintf (F, "edge: { sourcename: \"");
529 fprintf (F, "\" targetname: \"%p\" "
530 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
533 xfprintf (F, "edge: { sourcename: \"");
535 fprintf (F, "\" targetname: \"%p\" "
536 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
539 xfprintf (F, "edge: { sourcename: \"");
541 fprintf (F, "\" targetname: \"%p\" "
542 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
550 void dump_const_expression(ir_node *value) {
551 ir_graph *rem = current_ir_graph;
552 current_ir_graph = get_const_code_irg();
553 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
554 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
555 current_ir_graph = rem;
559 void print_type_info(type *tp) {
560 if (get_type_state(tp) == layout_undefined) {
561 xfprintf(F, "state: layout_undefined\n");
563 xfprintf(F, "state: layout_fixed,\n");
565 if (get_type_mode(tp))
566 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
567 xfprintf(F, "size: %dB,\n", get_type_size(tp));
571 void print_typespecific_info(type *tp) {
572 switch (get_type_tpop_code(tp)) {
575 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
579 xfprintf (F, " " TYPE_METH_NODE_ATTR);
590 case tpo_enumeration:
603 void print_type_node(type *tp) {
604 xfprintf (F, "node: {title: \"%p\" ", tp);
605 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
606 xfprintf (F, "info1: \"");
609 print_typespecific_info(tp);
613 /* dumps a type or entity and it's edges. */
615 dump_type_info (type_or_ent *tore, void *env) {
616 int i = 0; /* to shutup gcc */
618 /* dump this type or entity */
620 switch (get_kind(tore)) {
623 entity *ent = (entity *)tore;
626 xfprintf (F, "node: {title: \"%p\" ", tore);
627 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
628 xfprintf (F, "label: ");
629 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
630 if(dynamic_allocated == get_entity_allocation(ent))
631 xfprintf (F, " info1:\"dynamic allocated\n");
633 xfprintf (F, " info1:\"static allocated\n");
634 switch (get_entity_visibility(ent)) {
635 case local: fprintf (F, "local\n"); break;
636 case external_visible: fprintf (F, "external_visible\n"); break;
637 case external_allocated: fprintf (F, "external_allocate\nd");break;
639 switch (get_entity_variability(ent)) {
640 case uninitialized: fprintf (F, "uninitialized");break;
641 case initialized: fprintf (F, "initialized"); break;
642 case part_constant: fprintf (F, "part_constant");break;
643 case constant: fprintf (F, "constant"); break;
645 xfprintf(F, "\"}\n");
647 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
648 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
649 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
650 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
651 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
652 for(i = 0; i < get_entity_n_overwrites(ent); i++)
653 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
654 ENT_OVERWRITES_EDGE_ATTR "}\n", ent, get_entity_overwrites(ent, i));
655 /* attached subgraphs */
656 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
657 if (is_atomic_entity(ent)) {
658 value = get_atomic_ent_value(ent);
659 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
661 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
662 dump_const_expression(value);
664 if (is_compound_entity(ent)) {
665 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
666 value = get_compound_ent_value(ent, i);
667 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
669 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
670 dump_const_expression(value);
671 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
672 ENT_CORR_EDGE_ATTR "}\n", ent,
673 get_compound_ent_value_member(ent, i), i);
680 type *tp = (type *)tore;
682 /* and now the edges */
683 switch (get_type_tpop_code(tp)) {
686 for (i=0; i < get_class_n_supertype(tp); i++)
687 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
688 TYPE_SUPER_EDGE_ATTR "}\n",
689 tp, get_class_supertype(tp, i));
690 for (i=0; i < get_class_n_member(tp); i++)
691 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
692 TYPE_MEMBER_EDGE_ATTR "}\n",
693 tp, get_class_member(tp, i));
697 for (i=0; i < get_struct_n_member(tp); i++)
698 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
699 TYPE_MEMBER_EDGE_ATTR "}\n",
700 tp, get_struct_member(tp, i));
704 for (i = 0; i < get_method_n_params(tp); i++)
705 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
706 METH_PAR_EDGE_ATTR "}\n",
707 tp, get_method_param_type(tp, i), i);
708 for (i = 0; i < get_method_n_res(tp); i++)
709 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
710 METH_RES_EDGE_ATTR "}\n",
711 tp, get_method_res_type(tp, i), i);
715 for (i = 0; i < get_union_n_members(tp); i++)
716 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
717 "label: \"\"f" UNION_EDGE_ATTR "}\n",
718 tp, get_union_member(tp, i));
722 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
723 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
724 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
725 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
727 case tpo_enumeration:
732 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
733 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
734 get_pointer_points_to_type(tp), i);
742 break; /* case k_type */
745 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
747 } /* switch kind_or_entity */
750 /************************************************************************/
751 /* open and close vcg file */
752 /************************************************************************/
754 void vcg_open (ir_graph *irg, char *suffix) {
755 char *fname; /* filename to put the vcg information in */
762 /** open file for vcg graph */
763 ent = get_irg_ent(irg);
764 id = ent->ld_name ? ent->ld_name : ent->name;
765 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
766 len = id_to_strlen (id);
768 fname = malloc (len + 5 + strlen(suffix));
769 strncpy (fname, cp, len); /* copy the filename */
771 strcat (fname, suffix); /* append file suffix */
773 fname = malloc (len + 5 + strlen(suffix));
774 strncpy (fname, cp, len); /* copy the filename */
775 fname[len] = '\0'; /* ensure string termination */
776 /*strcpy (fname, cp); * copy the filename *
777 this produces wrong, too long strings in conjuction with the
778 jocca frontend. The \0 seems to be missing. */
779 strcat (fname, suffix); /* append file suffix */
780 strcat (fname, ".vcg"); /* append the .vcg suffix */
781 F = fopen (fname, "w"); /* open file for writing */
783 panic ("cannot open %s for writing (%m)", fname); /* not reached */
787 strcpy(label, "yes");
789 strcpy (label, "no");
794 "graph: { title: \"ir graph of %s\"\n"
795 "display_edge_labels: %s\n"
796 "layoutalgorithm: mindepth\n"
797 "manhattan_edges: yes\n"
799 "orientation: bottom_to_top\n"
800 "classname 1: \"Data\"\n"
801 "classname 2: \"Block\"\n"
802 "classname 3: \"Entity type\""
803 "classname 4: \"Entity owner\""
804 "classname 5: \"Method Param\""
805 "classname 6: \"Method Res\""
806 "classname 7: \"Super\""
807 "classname 8: \"Union\""
808 "classname 9: \"Points-to\""
809 "classname 10: \"Array Element Type\""
810 "classname 11: \"Overwrites\""
811 "classname 12: \"Member\""
814 xfprintf (F, "\n"); /* a separator */
817 void vcg_open_name (const char *name) {
818 char *fname; /* filename to put the vcg information in */
822 /** open file for vcg graph */
824 fname = malloc (len + 5);
825 strcpy (fname, name); /* copy the filename */
826 strcat (fname, ".vcg"); /* append the .vcg suffix */
827 F = fopen (fname, "w"); /* open file for writing */
829 panic ("cannot open %s for writing (%m)", fname); /* not reached */
833 strcpy(label, "yes");
835 strcpy (label, "no");
840 "graph: { title: \"ir graph of %s\"\n"
841 "display_edge_labels: %s\n"
842 "layoutalgorithm: mindepth\n"
843 "manhattan_edges: yes\n"
845 "orientation: bottom_to_top\n"
846 "classname 1: \"Data\"\n"
847 "classname 2: \"Block\"\n"
848 "classname 3: \"Entity type\"\n"
849 "classname 4: \"Entity owner\"\n"
850 "classname 5: \"Method Param\"\n"
851 "classname 6: \"Method Res\"\n"
852 "classname 7: \"Super\"\n"
853 "classname 8: \"Union\"\n"
854 "classname 9: \"Points-to\"\n"
855 "classname 10: \"Array Element Type\"\n"
856 "classname 11: \"Overwrites\"\n"
857 "classname 12: \"Member\"\n"
860 xfprintf (F, "\n"); /* a separator */
865 xfprintf (F, "}\n"); /* print footer */
866 fclose (F); /* close vcg file */
869 /************************************************************************/
870 /* routines to dump a graph, blocks as conventional nodes. */
871 /************************************************************************/
874 dump_whole_node (ir_node *n, void* env) {
876 if (!node_floats(n)) dump_ir_block_edge(n);
877 dump_ir_data_edges(n);
881 dump_ir_graph (ir_graph *irg)
884 rem = current_ir_graph;
885 current_ir_graph = irg;
889 /* walk over the graph */
890 irg_walk(irg->end, dump_whole_node, NULL, NULL);
892 /* dump the out edges in a separate walk */
893 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
894 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
899 current_ir_graph = rem;
902 /***********************************************************************/
903 /* the following routines dump the nodes as attached to the blocks. */
904 /***********************************************************************/
906 int node_floats(ir_node *n) {
907 return ((get_op_pinned(get_irn_op(n)) == floats) &&
908 (get_irg_pinned(current_ir_graph) == floats));
912 dump_ir_blocks_nodes (ir_node *n, void *env) {
913 ir_node *block = (ir_node *)env;
915 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
917 dump_ir_data_edges(n);
919 if (get_irn_op(n) == op_Bad)
924 dump_ir_block (ir_node *block, void *env) {
925 ir_graph *irg = (ir_graph *)env;
927 if (get_irn_opcode(block) == iro_Block) {
929 /* This is a block. So dump the vcg information to make a block. */
930 xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\" label: \"");
932 xfprintf (F, "%ld", get_irn_node_nr(block));
934 xfprintf (F, "%I", block->op->name);
936 xfprintf(F, "\" status:clustered color:%s \n",
937 get_Block_matured (block) ? "yellow" : "red");
938 /* dump the blocks edges */
939 dump_ir_data_edges(block);
941 /* dump the nodes that go into the block */
942 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
944 /* Close the vcg information for the block */
945 xfprintf(F, "}\n\n");
951 dump_blockless_nodes (ir_node *n, void *env) {
952 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
954 dump_ir_data_edges(n);
955 dump_ir_block_edge(n);
956 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
959 if (node_floats(n)) {
961 dump_ir_data_edges(n);
962 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
966 void dump_ir_block_graph_2 (ir_graph *irg)
969 /* walk over the blocks in the graph */
970 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
972 /* dump all nodes that are not in a Block */
973 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
975 /* dump the Bad node */
977 dump_node(get_irg_bad(irg));
981 dump_ir_block_graph (ir_graph *irg)
984 rem = current_ir_graph;
985 current_ir_graph = irg;
989 dump_ir_block_graph_2 (irg);
992 current_ir_graph = rem;
996 /***********************************************************************/
997 /* the following routines dump a control flow graph */
998 /***********************************************************************/
1002 dump_block_to_cfg (ir_node *block, void *env) {
1006 if (get_irn_opcode(block) == iro_Block) {
1007 /* This is a block. Dump a node for the block. */
1008 xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
1010 /* Dump the edges */
1011 for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
1012 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1013 xfprintf (F, "edge: { sourcename: \"");
1014 PRINT_NODEID(block);
1015 fprintf (F, "\" targetname: \"");
1017 fprintf (F, "\" }\n");
1023 dump_cfg (ir_graph *irg)
1025 vcg_open (irg, "-cfg");
1027 /* walk over the blocks in the graph */
1028 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1034 /***********************************************************************/
1035 /* the following routine dumps all type information reachable from an */
1037 /***********************************************************************/
1041 dump_type_graph (ir_graph *irg)
1044 rem = current_ir_graph;
1045 current_ir_graph = irg;
1047 vcg_open (irg, "-type");
1049 /* walk over the blocks in the graph */
1050 type_walk_irg(irg, dump_type_info, NULL, NULL);
1051 /* The walker for the const code can be called several times for the
1052 same (sub) experssion. So that no nodes are dumped several times
1053 we decrease the visited flag of the corresponding graph after each
1054 walk. So now increase it finally. */
1055 inc_irg_visited(get_const_code_irg());
1058 current_ir_graph = rem;
1061 /***********************************************************************/
1062 /* the following routine dumps all type information */
1063 /***********************************************************************/
1067 dump_all_types (void)
1069 vcg_open_name ("All_types");
1070 type_walk(dump_type_info, NULL, NULL);
1071 inc_irg_visited(get_const_code_irg());
1075 /***********************************************************************/
1076 /* dumps a graph with type information */
1077 /***********************************************************************/
1081 dump_ir_graph_w_types (ir_graph *irg)
1084 rem = current_ir_graph;
1085 current_ir_graph = irg;
1087 vcg_open (irg, "-all");
1089 /* dump common ir graph */
1090 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1091 /* dump type info */
1092 type_walk_irg(irg, dump_type_info, NULL, NULL);
1093 inc_irg_visited(get_const_code_irg());
1094 /* dump edges from graph to type info */
1095 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1098 current_ir_graph = rem;
1102 dump_ir_block_graph_w_types (ir_graph *irg)
1105 rem = current_ir_graph;
1106 current_ir_graph = irg;
1108 vcg_open (irg, "-all");
1110 /* dump common blocked ir graph */
1111 dump_ir_block_graph_2(irg);
1112 /* dump type info */
1113 type_walk_irg(irg, dump_type_info, NULL, NULL);
1114 inc_irg_visited(get_const_code_irg());
1115 /* dump edges from graph to type info */
1116 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1119 current_ir_graph = rem;
1122 /***********************************************************************/
1123 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1125 /* dump_ir_block_graph */
1127 /* dump_type_graph */
1128 /* dump_ir_graph_w_types */
1129 /***********************************************************************/
1130 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1132 for (i=0; i < get_irp_n_irgs(); i++) {
1133 dump_graph(get_irp_irg(i));
1138 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1139 abort with a segmentation fault. */
1140 void turn_off_edge_labels() {
1144 void turn_off_constant_entity_values() {
1148 void dump_keepalive_edges() {
1152 void dump_out_edges() {
1153 dump_out_edge_flag = 1;