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 /* don't use get_SymConst_ptr_info as it mangles the name. */
106 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
108 assert(get_kind(get_SymConst_type(n)) == k_type);
109 assert(get_type_ident(get_SymConst_type(n)));
110 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
111 if (get_SymConst_kind == type_tag)
114 xfprintf (F, "size");
118 xfprintf (F, "%I", get_irn_opident(n));
123 dump_node_mode (ir_node *n)
125 switch (n->op->code) {
142 xfprintf (F, "%I", get_mode_ident(n->mode));
149 dump_node_nodeattr (ir_node *n)
151 switch (n->op->code) {
153 if (n->in[1]->op->code == iro_Cmp) {
154 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
156 xfprintf (F, "%ld", n->attr.proj);
160 assert(get_kind(get_Sel_entity(n)) == k_entity);
161 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
168 dump_node_vcgattr (ir_node *n)
170 switch (n->op->code) {
173 xfprintf (F, "color: blue");
176 xfprintf (F, "color: lightyellow");
179 xfprintf (F, "color: green");
184 xfprintf (F, "color: yellow");
187 xfprintf (F, DEFAULT_NODE_ATTR);
192 dump_node (ir_node *n) {
195 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
200 dump_node_nodeattr(n);
202 xfprintf (F, " %ld", get_irn_node_nr(n));
205 dump_node_vcgattr(n);
210 dump_ir_node (ir_node *n)
213 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
215 switch (n->op->code) { /* node label */
217 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
218 xfprintf (F, DEFAULT_NODE_ATTR);
221 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
222 xfprintf (F, DEFAULT_NODE_ATTR);
225 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
226 xfprintf (F, DEFAULT_NODE_ATTR);
229 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
230 if (get_irn_modecode(n) == irm_M)
231 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
233 xfprintf (F, DEFAULT_NODE_ATTR);
236 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
237 xfprintf (F, DEFAULT_NODE_ATTR);
240 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
241 xfprintf (F, DEFAULT_NODE_ATTR);
244 if (n->in[1]->op->code == iro_Cmp) {
245 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
246 get_pnc_string(n->attr.proj));
248 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
250 xfprintf (F, DEFAULT_NODE_ATTR);
253 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
254 xfprintf (F, DEFAULT_NODE_ATTR);
257 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
258 xfprintf (F, DEFAULT_NODE_ATTR);
261 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
262 xfprintf (F, DEFAULT_NODE_ATTR);
265 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
266 xfprintf (F, DEFAULT_NODE_ATTR);
269 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
270 xfprintf (F, DEFAULT_NODE_ATTR);
273 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
274 xfprintf (F, DEFAULT_NODE_ATTR);
277 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
278 xfprintf (F, DEFAULT_NODE_ATTR);
281 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
282 xfprintf (F, DEFAULT_NODE_ATTR);
285 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
286 xfprintf (F, DEFAULT_NODE_ATTR);
289 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
290 xfprintf (F, DEFAULT_NODE_ATTR);
293 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
294 xfprintf (F, DEFAULT_NODE_ATTR);
297 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
298 xfprintf (F, DEFAULT_NODE_ATTR);
301 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
302 xfprintf (F, DEFAULT_NODE_ATTR);
305 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
306 xfprintf (F, DEFAULT_NODE_ATTR);
309 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
310 xfprintf (F, DEFAULT_NODE_ATTR);
313 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
314 xfprintf (F, DEFAULT_NODE_ATTR);
317 xfprintf (F, "\"%I\"", get_irn_opident(n));
318 xfprintf (F, DEFAULT_NODE_ATTR);
321 xfprintf (F, "\"%I\"", get_irn_opident(n));
322 xfprintf (F, DEFAULT_NODE_ATTR);
325 xfprintf (F, "\"%I\"", get_irn_opident(n));
326 xfprintf (F, DEFAULT_NODE_ATTR);
329 xfprintf (F, "\"%I\"", get_irn_opident(n));
330 xfprintf (F, DEFAULT_NODE_ATTR);
333 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
334 xfprintf (F, DEFAULT_NODE_ATTR);
338 xfprintf (F, "\"%R\"", n);
339 xfprintf (F, DEFAULT_NODE_ATTR);
342 xfprintf (F, "\"%I\" ", get_irn_opident(n));
343 xfprintf (F, DEFAULT_NODE_ATTR);
346 assert(get_kind(get_Sel_entity(n)) == k_entity);
347 xfprintf (F, "\"%I ", get_irn_opident(n));
348 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
349 xfprintf (F, DEFAULT_NODE_ATTR);
352 assert(get_kind(get_SymConst_type(n)) == k_type);
353 assert(get_type_ident(get_SymConst_type(n)));
354 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
355 switch (n->attr.i.num){
357 xfprintf (F, "tag\" ");
360 xfprintf (F, "size\" ");
366 xfprintf (F, DEFAULT_NODE_ATTR);
369 xfprintf (F, "\"%I\" ", get_irn_opident(n));
370 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
373 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
374 xfprintf (F, DEFAULT_NODE_ATTR);
377 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
379 xfprintf (F, "}\n"); /* footer */
383 /* dump the edge to the block this node belongs to */
385 dump_ir_block_edge(ir_node *n) {
386 if (is_no_Block(n)) {
387 xfprintf (F, "edge: { sourcename: \"");
389 xfprintf (F, "\" targetname: \"");
390 PRINT_NODEID(get_nodes_Block(n));
391 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
395 void print_edge_vcgattr(ir_node *from, int to) {
398 switch (get_irn_opcode(from)) {
400 xfprintf (F, CF_EDGE_ATTR);
402 case iro_Start: break;
405 case iro_Cond: break;
408 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
410 case iro_Const: break;
411 case iro_SymConst:break;
414 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
418 case iro_Minus: break;
424 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
432 case iro_Shrs: break;
435 case iro_Conv: break;
437 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
443 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
446 xfprintf (F, MEM_EDGE_ATTR);
448 case iro_Tuple: break;
450 switch (get_irn_modecode(from)) {
452 xfprintf (F, CF_EDGE_ATTR);
455 xfprintf (F, MEM_EDGE_ATTR);
466 /* dump edges to our inputs */
468 dump_ir_data_edges(ir_node *n) {
471 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
474 for (i = 0; i < get_irn_arity(n); i++) {
475 assert(get_irn_n(n, i));
476 fprintf (F, "edge: {sourcename: \"");
478 fprintf (F, "\" targetname: \"");
479 PRINT_NODEID(get_irn_n(n, i));
481 fprintf (F, " label: \"%d\" ", i);
482 print_edge_vcgattr(n, i);
489 dump_out_edge (ir_node *n, void* env) {
491 for (i = 0; i < get_irn_n_outs(n); i++) {
492 assert(get_irn_out(n, i));
493 fprintf (F, "edge: {sourcename: \"");
495 fprintf (F, "\" targetname: \"");
496 PRINT_NODEID(get_irn_out(n, i));
497 fprintf (F, "\" color: red linestyle: dashed");
503 /* dumps the edges between nodes and their type or entity attributes. */
504 void dump_node2type_edges (ir_node *n, void *env)
508 switch (get_irn_opcode(n)) {
510 /* @@@ some consts have an entity */
513 if ( (get_SymConst_kind(n) == type_tag)
514 || (get_SymConst_kind(n) == size)) {
515 xfprintf (F, "edge: { sourcename: \"");
517 fprintf (F, "\" targetname: \"%p\" "
518 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
522 xfprintf (F, "edge: { sourcename: \"");
524 fprintf (F, "\" targetname: \"%p\" "
525 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
528 xfprintf (F, "edge: { sourcename: \"");
530 fprintf (F, "\" targetname: \"%p\" "
531 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
534 xfprintf (F, "edge: { sourcename: \"");
536 fprintf (F, "\" targetname: \"%p\" "
537 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
540 xfprintf (F, "edge: { sourcename: \"");
542 fprintf (F, "\" targetname: \"%p\" "
543 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
551 void dump_const_expression(ir_node *value) {
552 ir_graph *rem = current_ir_graph;
553 current_ir_graph = get_const_code_irg();
554 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
555 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
556 current_ir_graph = rem;
560 void print_type_info(type *tp) {
561 if (get_type_state(tp) == layout_undefined) {
562 xfprintf(F, "state: layout_undefined\n");
564 xfprintf(F, "state: layout_fixed,\n");
566 if (get_type_mode(tp))
567 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
568 xfprintf(F, "size: %dB,\n", get_type_size(tp));
572 void print_typespecific_info(type *tp) {
573 switch (get_type_tpop_code(tp)) {
576 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
580 xfprintf (F, " " TYPE_METH_NODE_ATTR);
591 case tpo_enumeration:
604 void print_type_node(type *tp) {
605 xfprintf (F, "node: {title: \"%p\" ", tp);
606 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
607 xfprintf (F, "info1: \"");
610 print_typespecific_info(tp);
614 /* dumps a type or entity and it's edges. */
616 dump_type_info (type_or_ent *tore, void *env) {
617 int i = 0; /* to shutup gcc */
619 /* dump this type or entity */
621 switch (get_kind(tore)) {
624 entity *ent = (entity *)tore;
627 xfprintf (F, "node: {title: \"%p\" ", tore);
628 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
629 xfprintf (F, "label: ");
630 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
631 if(dynamic_allocated == get_entity_allocation(ent))
632 xfprintf (F, " info1:\"dynamic allocated\n");
634 xfprintf (F, " info1:\"static allocated\n");
635 switch (get_entity_visibility(ent)) {
636 case local: fprintf (F, "local\n"); break;
637 case external_visible: fprintf (F, "external_visible\n"); break;
638 case external_allocated: fprintf (F, "external_allocate\n");break;
640 switch (get_entity_variability(ent)) {
641 case uninitialized: fprintf (F, "uninitialized");break;
642 case initialized: fprintf (F, "initialized"); break;
643 case part_constant: fprintf (F, "part_constant");break;
644 case constant: fprintf (F, "constant"); break;
646 if (is_method_type(get_entity_type(ent)))
647 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
648 xfprintf(F, "\"}\n");
650 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
651 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
652 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
653 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
654 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
655 for(i = 0; i < get_entity_n_overwrites(ent); i++)
656 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
657 ENT_OVERWRITES_EDGE_ATTR "}\n", ent, get_entity_overwrites(ent, i));
658 /* attached subgraphs */
659 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
660 if (is_atomic_entity(ent)) {
661 value = get_atomic_ent_value(ent);
662 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
664 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
665 dump_const_expression(value);
667 if (is_compound_entity(ent)) {
668 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
669 value = get_compound_ent_value(ent, i);
670 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
672 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
673 dump_const_expression(value);
674 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
675 ENT_CORR_EDGE_ATTR "}\n", ent,
676 get_compound_ent_value_member(ent, i), i);
683 type *tp = (type *)tore;
685 /* and now the edges */
686 switch (get_type_tpop_code(tp)) {
689 for (i=0; i < get_class_n_supertype(tp); i++)
690 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
691 TYPE_SUPER_EDGE_ATTR "}\n",
692 tp, get_class_supertype(tp, i));
693 for (i=0; i < get_class_n_member(tp); i++)
694 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
695 TYPE_MEMBER_EDGE_ATTR "}\n",
696 tp, get_class_member(tp, i));
700 for (i=0; i < get_struct_n_member(tp); i++)
701 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
702 TYPE_MEMBER_EDGE_ATTR "}\n",
703 tp, get_struct_member(tp, i));
707 for (i = 0; i < get_method_n_params(tp); i++)
708 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
709 METH_PAR_EDGE_ATTR "}\n",
710 tp, get_method_param_type(tp, i), i);
711 for (i = 0; i < get_method_n_res(tp); i++)
712 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
713 METH_RES_EDGE_ATTR "}\n",
714 tp, get_method_res_type(tp, i), i);
718 for (i = 0; i < get_union_n_members(tp); i++)
719 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
720 "label: \"\"f" UNION_EDGE_ATTR "}\n",
721 tp, get_union_member(tp, i));
725 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
726 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
727 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
728 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
730 case tpo_enumeration:
735 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
736 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
737 get_pointer_points_to_type(tp), i);
745 break; /* case k_type */
748 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
750 } /* switch kind_or_entity */
753 /************************************************************************/
754 /* open and close vcg file */
755 /************************************************************************/
757 void vcg_open (ir_graph *irg, char *suffix) {
758 char *fname; /* filename to put the vcg information in */
765 /** open file for vcg graph */
766 ent = get_irg_ent(irg);
767 id = ent->ld_name ? ent->ld_name : ent->name;
768 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
769 len = id_to_strlen (id);
771 fname = malloc (len + 5 + strlen(suffix));
772 strncpy (fname, cp, len); /* copy the filename */
774 strcat (fname, suffix); /* append file suffix */
776 fname = malloc (len + 5 + strlen(suffix));
777 strncpy (fname, cp, len); /* copy the filename */
778 fname[len] = '\0'; /* ensure string termination */
779 /*strcpy (fname, cp); * copy the filename *
780 this produces wrong, too long strings in conjuction with the
781 jocca frontend. The \0 seems to be missing. */
782 strcat (fname, suffix); /* append file suffix */
783 strcat (fname, ".vcg"); /* append the .vcg suffix */
784 F = fopen (fname, "w"); /* open file for writing */
786 panic ("cannot open %s for writing (%m)", fname); /* not reached */
790 strcpy(label, "yes");
792 strcpy (label, "no");
797 "graph: { title: \"ir graph of %s\"\n"
798 "display_edge_labels: %s\n"
799 "layoutalgorithm: mindepth\n"
800 "manhattan_edges: yes\n"
802 "orientation: bottom_to_top\n"
803 "classname 1: \"Data\"\n"
804 "classname 2: \"Block\"\n"
805 "classname 3: \"Entity type\""
806 "classname 4: \"Entity owner\""
807 "classname 5: \"Method Param\""
808 "classname 6: \"Method Res\""
809 "classname 7: \"Super\""
810 "classname 8: \"Union\""
811 "classname 9: \"Points-to\""
812 "classname 10: \"Array Element Type\""
813 "classname 11: \"Overwrites\""
814 "classname 12: \"Member\""
817 xfprintf (F, "\n"); /* a separator */
820 void vcg_open_name (const char *name) {
821 char *fname; /* filename to put the vcg information in */
825 /** open file for vcg graph */
827 fname = malloc (len + 5);
828 strcpy (fname, name); /* copy the filename */
829 strcat (fname, ".vcg"); /* append the .vcg suffix */
830 F = fopen (fname, "w"); /* open file for writing */
832 panic ("cannot open %s for writing (%m)", fname); /* not reached */
836 strcpy(label, "yes");
838 strcpy (label, "no");
843 "graph: { title: \"ir graph of %s\"\n"
844 "display_edge_labels: %s\n"
845 "layoutalgorithm: mindepth\n"
846 "manhattan_edges: yes\n"
848 "orientation: bottom_to_top\n"
849 "classname 1: \"Data\"\n"
850 "classname 2: \"Block\"\n"
851 "classname 3: \"Entity type\"\n"
852 "classname 4: \"Entity owner\"\n"
853 "classname 5: \"Method Param\"\n"
854 "classname 6: \"Method Res\"\n"
855 "classname 7: \"Super\"\n"
856 "classname 8: \"Union\"\n"
857 "classname 9: \"Points-to\"\n"
858 "classname 10: \"Array Element Type\"\n"
859 "classname 11: \"Overwrites\"\n"
860 "classname 12: \"Member\"\n"
863 xfprintf (F, "\n"); /* a separator */
868 xfprintf (F, "}\n"); /* print footer */
869 fclose (F); /* close vcg file */
872 /************************************************************************/
873 /* routines to dump a graph, blocks as conventional nodes. */
874 /************************************************************************/
877 dump_whole_node (ir_node *n, void* env) {
879 if (!node_floats(n)) dump_ir_block_edge(n);
880 dump_ir_data_edges(n);
884 dump_ir_graph (ir_graph *irg)
887 rem = current_ir_graph;
888 current_ir_graph = irg;
892 /* walk over the graph */
893 irg_walk(irg->end, dump_whole_node, NULL, NULL);
895 /* dump the out edges in a separate walk */
896 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
897 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
902 current_ir_graph = rem;
905 /***********************************************************************/
906 /* the following routines dump the nodes as attached to the blocks. */
907 /***********************************************************************/
909 int node_floats(ir_node *n) {
910 return ((get_op_pinned(get_irn_op(n)) == floats) &&
911 (get_irg_pinned(current_ir_graph) == floats));
915 dump_ir_blocks_nodes (ir_node *n, void *env) {
916 ir_node *block = (ir_node *)env;
918 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
920 dump_ir_data_edges(n);
922 if (get_irn_op(n) == op_Bad)
927 dump_ir_block (ir_node *block, void *env) {
928 ir_graph *irg = (ir_graph *)env;
930 if (get_irn_opcode(block) == iro_Block) {
932 /* This is a block. So dump the vcg information to make a block. */
933 xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\" label: \"");
935 xfprintf (F, "%ld", get_irn_node_nr(block));
937 xfprintf (F, "%I", block->op->name);
939 xfprintf(F, "\" status:clustered color:%s \n",
940 get_Block_matured (block) ? "yellow" : "red");
941 /* dump the blocks edges */
942 dump_ir_data_edges(block);
944 /* dump the nodes that go into the block */
945 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
947 /* Close the vcg information for the block */
948 xfprintf(F, "}\n\n");
954 dump_blockless_nodes (ir_node *n, void *env) {
955 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
957 dump_ir_data_edges(n);
958 dump_ir_block_edge(n);
959 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
962 if (node_floats(n)) {
964 dump_ir_data_edges(n);
965 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
969 void dump_ir_block_graph_2 (ir_graph *irg)
972 /* walk over the blocks in the graph */
973 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
975 /* dump all nodes that are not in a Block */
976 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
978 /* dump the Bad node */
980 dump_node(get_irg_bad(irg));
984 dump_ir_block_graph (ir_graph *irg)
987 rem = current_ir_graph;
988 current_ir_graph = irg;
992 dump_ir_block_graph_2 (irg);
995 current_ir_graph = rem;
999 /***********************************************************************/
1000 /* the following routines dump a control flow graph */
1001 /***********************************************************************/
1005 dump_block_to_cfg (ir_node *block, void *env) {
1009 if (get_irn_opcode(block) == iro_Block) {
1010 /* This is a block. Dump a node for the block. */
1011 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1012 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1013 xfprintf (F, "\"}\n");
1014 /* Dump the edges */
1015 for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
1016 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1017 xfprintf (F, "edge: { sourcename: \"");
1018 PRINT_NODEID(block);
1019 fprintf (F, "\" targetname: \"");
1021 fprintf (F, "\" }\n");
1027 dump_cfg (ir_graph *irg)
1029 vcg_open (irg, "-cfg");
1031 /* walk over the blocks in the graph */
1032 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1038 /***********************************************************************/
1039 /* the following routine dumps all type information reachable from an */
1041 /***********************************************************************/
1045 dump_type_graph (ir_graph *irg)
1048 rem = current_ir_graph;
1049 current_ir_graph = irg;
1051 vcg_open (irg, "-type");
1053 /* walk over the blocks in the graph */
1054 type_walk_irg(irg, dump_type_info, NULL, NULL);
1055 /* The walker for the const code can be called several times for the
1056 same (sub) experssion. So that no nodes are dumped several times
1057 we decrease the visited flag of the corresponding graph after each
1058 walk. So now increase it finally. */
1059 inc_irg_visited(get_const_code_irg());
1062 current_ir_graph = rem;
1065 /***********************************************************************/
1066 /* the following routine dumps all type information */
1067 /***********************************************************************/
1071 dump_all_types (void)
1073 vcg_open_name ("All_types");
1074 type_walk(dump_type_info, NULL, NULL);
1075 inc_irg_visited(get_const_code_irg());
1079 /***********************************************************************/
1080 /* dumps a graph with type information */
1081 /***********************************************************************/
1085 dump_ir_graph_w_types (ir_graph *irg)
1088 rem = current_ir_graph;
1089 current_ir_graph = irg;
1091 vcg_open (irg, "-all");
1093 /* dump common ir graph */
1094 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1095 /* dump type info */
1096 type_walk_irg(irg, dump_type_info, NULL, NULL);
1097 inc_irg_visited(get_const_code_irg());
1098 /* dump edges from graph to type info */
1099 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1102 current_ir_graph = rem;
1106 dump_ir_block_graph_w_types (ir_graph *irg)
1109 rem = current_ir_graph;
1110 current_ir_graph = irg;
1112 vcg_open (irg, "-all");
1114 /* dump common blocked ir graph */
1115 dump_ir_block_graph_2(irg);
1116 /* dump type info */
1117 type_walk_irg(irg, dump_type_info, NULL, NULL);
1118 inc_irg_visited(get_const_code_irg());
1119 /* dump edges from graph to type info */
1120 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1123 current_ir_graph = rem;
1126 /***********************************************************************/
1127 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1129 /* dump_ir_block_graph */
1131 /* dump_type_graph */
1132 /* dump_ir_graph_w_types */
1133 /***********************************************************************/
1134 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1136 for (i=0; i < get_irp_n_irgs(); i++) {
1137 dump_graph(get_irp_irg(i));
1142 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1143 abort with a segmentation fault. */
1144 void turn_off_edge_labels() {
1148 void turn_off_constant_entity_values() {
1152 void dump_keepalive_edges() {
1156 void dump_out_edges() {
1157 dump_out_edge_flag = 1;