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
10 # include "irgraph_t.h"
20 # include "type_or_entity.h"
22 # include "typewalk.h"
24 #define DEFAULT_NODE_ATTR ""
25 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
26 #define NODE2TYPE_EDGE_ATTR ""
27 #define DEFAULT_TYPE_ATTRIBUTE ""
28 #define TYPE_EDGE_ATTR ""
30 #define PRINT_NODEID(X) fprintf(F, "%p", X)
36 /*******************************************************************/
37 /* routines to dump information about a single node */
38 /*******************************************************************/
43 dump_node_opcode (ir_node *n)
46 if (n->op->code == iro_Const) {
47 xfprintf (F, "%v", n->attr.con);
49 } else if (n->op->code == iro_SymConst) {
50 if (get_SymConst_kind(n) == linkage_ptr_info) {
51 xfprintf (F, "%I", get_SymConst_ptrinfo(n));
53 assert(get_kind(get_SymConst_type(n)) == k_type_class);
54 assert(get_class_ident((type_class *)get_SymConst_type(n)));
55 xfprintf (F, "%s ", id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
56 if (get_SymConst_kind == type_tag)
63 xfprintf (F, "%I", get_irn_opident(n));
68 dump_node_mode (ir_node *n)
70 switch (n->op->code) {
87 xfprintf (F, "%I", get_mode_ident(n->mode));
94 dump_node_nodeattr (ir_node *n)
96 switch (n->op->code) {
98 if (n->in[1]->op->code == iro_Cmp) {
99 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
101 xfprintf (F, "%ld", n->attr.proj);
105 /*assert(n->attr.s.ent->kind == k_entity);*/
106 assert(get_kind(get_Sel_entity(n)) == k_entity);
107 xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
109 /* xdoesn't work for some reason.
110 fprintf (F, "\"%I %I\" ", get_irn_opident(n), n->attr.s.ent); */
117 dump_node_vcgattr (ir_node *n)
119 switch (n->op->code) {
122 xfprintf (F, "color: blue");
125 xfprintf (F, "color: lightyellow");
128 xfprintf (F, "color: green");
133 xfprintf (F, "color: yellow");
136 xfprintf (F, DEFAULT_NODE_ATTR);
141 dump_node (ir_node *n) {
144 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
149 dump_node_nodeattr(n);
151 xfprintf (F, " %ld", get_irn_node_nr(n));
154 dump_node_vcgattr(n);
159 dump_ir_node (ir_node *n)
162 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
164 switch (n->op->code) { /* node label */
166 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
167 xfprintf (F, DEFAULT_NODE_ATTR);
170 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
171 xfprintf (F, DEFAULT_NODE_ATTR);
174 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
175 xfprintf (F, DEFAULT_NODE_ATTR);
178 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
179 if (get_irn_modecode(n) == irm_M)
180 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
182 xfprintf (F, DEFAULT_NODE_ATTR);
185 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
186 xfprintf (F, DEFAULT_NODE_ATTR);
189 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
190 xfprintf (F, DEFAULT_NODE_ATTR);
193 if (n->in[1]->op->code == iro_Cmp) {
194 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
195 get_pnc_string(n->attr.proj));
197 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
199 xfprintf (F, DEFAULT_NODE_ATTR);
202 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
203 xfprintf (F, DEFAULT_NODE_ATTR);
206 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
207 xfprintf (F, DEFAULT_NODE_ATTR);
210 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
211 xfprintf (F, DEFAULT_NODE_ATTR);
214 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
215 xfprintf (F, DEFAULT_NODE_ATTR);
218 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
219 xfprintf (F, DEFAULT_NODE_ATTR);
222 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
223 xfprintf (F, DEFAULT_NODE_ATTR);
226 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
227 xfprintf (F, DEFAULT_NODE_ATTR);
230 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
231 xfprintf (F, DEFAULT_NODE_ATTR);
234 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
235 xfprintf (F, DEFAULT_NODE_ATTR);
238 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
239 xfprintf (F, DEFAULT_NODE_ATTR);
242 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
243 xfprintf (F, DEFAULT_NODE_ATTR);
246 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
247 xfprintf (F, DEFAULT_NODE_ATTR);
250 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
251 xfprintf (F, DEFAULT_NODE_ATTR);
254 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
255 xfprintf (F, DEFAULT_NODE_ATTR);
258 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
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\"", get_irn_opident(n));
267 xfprintf (F, DEFAULT_NODE_ATTR);
270 xfprintf (F, "\"%I\"", get_irn_opident(n));
271 xfprintf (F, DEFAULT_NODE_ATTR);
274 xfprintf (F, "\"%I\"", get_irn_opident(n));
275 xfprintf (F, DEFAULT_NODE_ATTR);
278 xfprintf (F, "\"%I\"", get_irn_opident(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);
287 xfprintf (F, "\"%R\"", n);
288 xfprintf (F, DEFAULT_NODE_ATTR);
291 xfprintf (F, "\"%I\" ", get_irn_opident(n));
292 xfprintf (F, DEFAULT_NODE_ATTR);
295 assert(get_kind(get_Sel_entity(n)) == k_entity);
296 xfprintf (F, "\"%I ", get_irn_opident(n));
297 xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
298 /* xdoesn't work for some reason.
299 fprintf (F, "\"%I %I\" ", get_irn_opident(n), get_entity_ident(get_Sel_entity(n))); */
300 xfprintf (F, DEFAULT_NODE_ATTR);
303 assert(get_kind(get_SymConst_type(n)) == k_type_class);
304 assert(get_class_ident((type_class *)get_SymConst_type(n)));
305 xfprintf (F, "\"%s ",
306 id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
307 switch (n->attr.i.num){
309 xfprintf (F, "tag\" ");
312 xfprintf (F, "size\" ");
318 xfprintf (F, DEFAULT_NODE_ATTR);
321 xfprintf (F, "\"%I\" ", get_irn_opident(n));
322 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
325 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
326 xfprintf (F, DEFAULT_NODE_ATTR);
329 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
331 xfprintf (F, "}\n"); /* footer */
335 /* dump the edge to the block this node belongs to */
337 dump_ir_block_edge(ir_node *n) {
339 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
340 BLOCK_EDGE_ATTR "}\n", n, get_nodes_Block(n));
344 /* dump edges to our inputs */
346 dump_ir_data_edges(ir_node *n) {
349 for (i = 0; i < get_irn_arity(n); i++) {
350 assert(get_irn_n(n, i));
351 xfprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\"",
353 fprintf (F, " label: \"%d\"", i+1);
358 /* dumps the edges between nodes and their type or entity attributes. */
359 void dump_node2type_edges (ir_node *n, void *env)
363 switch (get_irn_opcode(n)) {
365 if ( (get_SymConst_kind(n) == type_tag)
366 || (get_SymConst_kind(n) == size))
367 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
368 NODE2TYPE_EDGE_ATTR "}\n", n, get_SymConst_type(n));
371 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
372 NODE2TYPE_EDGE_ATTR "}\n", n, get_Sel_entity(n));
375 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
376 NODE2TYPE_EDGE_ATTR "}\n", n, get_Call_type(n));
379 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
380 NODE2TYPE_EDGE_ATTR "}\n", n, get_Alloc_type(n));
383 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
384 NODE2TYPE_EDGE_ATTR "}\n", n, get_Free_type(n));
392 /* dumps a type or entity and it's edges. */
394 dump_type_info (type_or_ent *tore, void *env) {
395 int i = 0; /* to shutup gcc */
397 /* dump this type or entity */
398 xfprintf (F, "node: {title: \"%p\" ", tore);
399 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
400 xfprintf (F, "label: ");
402 switch (get_kind(tore)) {
405 entity *ent = (entity *)tore;
406 xfprintf (F, "\"ent %I\"}\n", get_entity_ident(ent));
407 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
409 TYPE_EDGE_ATTR "}\n", tore, get_entity_owner(ent));
410 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
412 TYPE_EDGE_ATTR "}\n", tore, get_entity_type(ent));
416 type_class *type = (type_class *)tore;
417 xfprintf (F, "\"class %I\"}\n", get_class_ident(type));
418 for (i=0; i < get_class_n_supertype(type); i++)
419 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
420 " label: \"supertype\" " TYPE_EDGE_ATTR "}\n",
421 type, get_class_supertype(type, i));
425 type_strct *type = (type_strct *)tore;
426 xfprintf (F, "\"strct %I\"}\n", get_strct_ident(type));
430 type_method *type = (type_method *)tore;
431 xfprintf (F, "\"meth %I\"}\n", get_method_ident(type));
432 for (i = 0; i < get_method_arity(type); i++)
433 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
434 " label: \"param %d\" " TYPE_EDGE_ATTR "}\n",
435 tore, get_method_param_type(type, i), i);
436 for (i = 0; i < get_method_n_res(type); i++)
437 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
438 " label: \"res %d\" " TYPE_EDGE_ATTR "}\n",
439 tore, get_method_res_type(type, i), i);
443 type_union *type = (type_union *)tore;
444 xfprintf (F, "\"union %I\"}\n", get_union_ident(type));
449 type_array *type = (type_array *)tore;
450 xfprintf (F, "\"array %I\"}\n", get_array_ident(type));
451 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
452 TYPE_EDGE_ATTR "}\n", tore, get_array_element_type(type), i);
454 case k_type_enumeration:
456 type_enumeration *type = (type_enumeration *)tore;
457 xfprintf (F, "\"enum %I\"}\n", get_enumeration_ident(type));
461 type_pointer *type = (type_pointer *)tore;
462 xfprintf (F, "\"ptr %I\"}\n", get_pointer_ident(type));
463 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
464 TYPE_EDGE_ATTR "}\n", tore,
465 get_pointer_points_to_type(type), i);
467 case k_type_primitive:
469 type_primitive *type = (type_primitive *)tore;
470 xfprintf (F, "\"prim %I, mode %I\"}\n", get_primitive_ident(type),
471 get_mode_ident(get_primitive_mode(type)));
475 xfprintf (F, "\" faulty type \"}\n");
476 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
481 /************************************************************************/
482 /* open and close vcg file */
483 /************************************************************************/
485 void vcg_open (ir_graph *irg, char *suffix) {
486 char *fname; /* filename to put the vcg information in */
491 /** open file for vcg graph */
492 id = get_entity_ld_name (get_irg_ent(irg));
493 len = id_to_strlen (id);
496 fname = malloc (len + 5 + strlen(suffix));
497 strncpy (fname, cp, len); /* copy the filename */
499 strcat (fname, suffix); /* append file suffix */
501 fname = malloc (len + 5 + strlen(suffix));
502 strncpy (fname, cp, len); /* copy the filename */
503 fname[len] = '\0'; /* ensure string termination */
504 /*strcpy (fname, cp); * copy the filename *
505 this produces wrong, too long strings in conjuction with the
506 jocca frontend. The \0 seems to be missing. */
507 strcat (fname, suffix); /* append file suffix */
508 strcat (fname, ".vcg"); /* append the .vcg suffix */
509 F = fopen (fname, "w"); /* open file for writing */
511 panic ("cannot open %s for writing (%m)", fname); /* not reached */
516 "graph: { title: \"ir graph of %s\"\n"
517 "display_edge_labels: yes\n"
518 "layoutalgorithm: mindepth\n"
519 "manhattan_edges: yes\n"
521 "orientation: bottom_to_top\n"
522 "classname 1: \"Data\"\n"
523 "classname 2: \"Block\"\n", cp);
525 xfprintf (F, "\n"); /* a separator */
528 void vcg_open_name (const char *name) {
529 char *fname; /* filename to put the vcg information in */
532 /** open file for vcg graph */
534 fname = malloc (len + 5);
535 strcpy (fname, name); /* copy the filename */
536 strcat (fname, ".vcg"); /* append the .vcg suffix */
537 F = fopen (fname, "w"); /* open file for writing */
539 panic ("cannot open %s for writing (%m)", fname); /* not reached */
544 "graph: { title: \"ir graph of %s\"\n"
545 "display_edge_labels: yes\n"
546 "layoutalgorithm: mindepth\n"
547 "manhattan_edges: yes\n"
549 "orientation: bottom_to_top\n"
550 "classname 1: \"Data\"\n"
551 "classname 2: \"Block\"\n", name);
553 xfprintf (F, "\n"); /* a separator */
558 xfprintf (F, "}\n"); /* print footer */
559 fclose (F); /* close vcg file */
562 /************************************************************************/
563 /* routines to dump a graph, blocks as conventional nodes. */
564 /************************************************************************/
567 dump_whole_node (ir_node *n, void* env) {
569 dump_ir_block_edge(n);
570 dump_ir_data_edges(n);
574 dump_ir_graph (ir_graph *irg)
577 rem = current_ir_graph;
578 current_ir_graph = irg;
582 /* walk over the graph */
583 irg_walk(irg->end, dump_whole_node, NULL, NULL);
587 current_ir_graph = rem;
590 /***********************************************************************/
591 /* the following routines dump the nodes as attached to the blocks. */
592 /***********************************************************************/
595 dump_ir_blocks_nodes (ir_node *n, void *env) {
596 ir_node *block = (ir_node *)env;
598 if (is_no_Block(n) && get_nodes_Block(n) == block) {
600 dump_ir_data_edges(n);
605 dump_ir_block (ir_node *block, void *env) {
606 ir_graph *irg = (ir_graph *)env;
608 if (get_irn_opcode(block) == iro_Block) {
610 /* This is a block. So dump the vcg information to make a block. */
611 xfprintf(F, "graph: { title: \""); PRINT_NODEID(block); fprintf(F, "\" label: \"");
613 xfprintf (F, "%ld", get_irn_node_nr(block));
615 xfprintf (F, "%I", block->op->name);
617 xfprintf(F, "\" status:clustered color:lightyellow \n");
618 /* dump the blocks edges */
619 dump_ir_data_edges(block);
621 /* dump the nodes that go into the block */
622 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
624 /* Close the vcg information for the block */
625 xfprintf(F, "}\n\n");
630 dump_ir_block_graph (ir_graph *irg)
633 rem = current_ir_graph;
634 current_ir_graph = irg;
638 /* walk over the blocks in the graph */
639 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
642 current_ir_graph = rem;
646 /***********************************************************************/
647 /* the following routines dump a control flow graph */
648 /***********************************************************************/
652 dump_block_to_cfg (ir_node *block, void *env) {
656 if (get_irn_opcode(block) == iro_Block) {
657 /* This is a block. Dump a node for the block. */
658 xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
661 for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
662 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
663 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" }\n",
670 dump_cfg (ir_graph *irg)
672 vcg_open (irg, "-cfg");
674 /* walk over the blocks in the graph */
675 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
681 /***********************************************************************/
682 /* the following routine dumps all type information reachable from an */
684 /***********************************************************************/
688 dump_type_graph (ir_graph *irg)
691 rem = current_ir_graph;
692 current_ir_graph = irg;
694 vcg_open (irg, "-type");
696 /* walk over the blocks in the graph */
697 type_walk_irg(irg, dump_type_info, NULL, NULL);
700 current_ir_graph = rem;
703 /***********************************************************************/
704 /* the following routine dumps all type information */
705 /***********************************************************************/
709 dump_all_types (void)
711 vcg_open_name ("All_types");
712 type_walk(dump_type_info, NULL, NULL);
716 /***********************************************************************/
717 /* dumps a graph with type information */
718 /***********************************************************************/
722 dump_ir_graph_w_types (ir_graph *irg)
725 rem = current_ir_graph;
726 current_ir_graph = irg;
728 vcg_open (irg, "-all");
730 /* dump common ir graph */
731 /* irg_block_walk(irg->end, dump_ir_block, NULL, irg); */
732 irg_walk(irg->end, dump_whole_node, NULL, NULL);
734 type_walk_irg(irg, dump_type_info, NULL, NULL);
735 /* dump edges from graph to type info */
736 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
739 current_ir_graph = rem;
742 /***********************************************************************/
743 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
745 /* dump_ir_block_graph */
747 /* dump_type_graph */
748 /* dump_ir_graph_w_types */
749 /***********************************************************************/
750 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
752 for (i=0; i < get_irp_n_irgs(); i++) {
753 dump_graph(get_irp_irg(i));