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 ""
34 /*******************************************************************/
35 /* routines to dump information about a single node */
36 /*******************************************************************/
41 dump_node_opcode (ir_node *n)
44 if (n->op->code == iro_Const) {
45 xfprintf (F, "%v", n->attr.con);
47 } else if (n->op->code == iro_SymConst) {
48 if (get_SymConst_kind(n) == linkage_ptr_info) {
49 xfprintf (F, "%I", get_SymConst_ptrinfo(n));
51 assert(get_kind(get_SymConst_type(n)) == k_type_class);
52 assert(get_class_ident((type_class *)get_SymConst_type(n)));
53 xfprintf (F, "%s ", id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
54 if (get_SymConst_kind == type_tag)
61 xfprintf (F, "%I", n->op->name);
66 dump_node_mode (ir_node *n)
68 switch (n->op->code) {
85 xfprintf (F, "%I", n->mode->name);
92 dump_node_nodeattr (ir_node *n)
94 switch (n->op->code) {
96 if (n->in[1]->op->code == iro_Cmp) {
97 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
99 xfprintf (F, "%ld", n->attr.proj);
103 /*assert(n->attr.s.ent->kind == k_entity);*/
104 assert(get_kind(get_Sel_entity(n)) == k_entity);
105 xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
107 /* xdoesn't work for some reason.
108 fprintf (F, "\"%I %I\" ", n->op->name, n->attr.s.ent); */
115 dump_node_vcgattr (ir_node *n)
117 switch (n->op->code) {
120 xfprintf (F, "color: blue");
123 xfprintf (F, "color: lightyellow");
126 xfprintf (F, "color: green");
131 xfprintf (F, "color: yellow");
134 xfprintf (F, DEFAULT_NODE_ATTR);
139 dump_node (ir_node *n) {
142 xfprintf (F, "node: {title: \"%p\" label: \"", n);
146 dump_node_nodeattr(n);
148 xfprintf (F, " %ld", get_irn_node_nr(n));
151 dump_node_vcgattr(n);
156 dump_ir_node (ir_node *n)
159 xfprintf (F, "node: {title: \"%p\" label: ", n);
161 switch (n->op->code) { /* node label */
163 xfprintf (F, "\"%I\" color: blue ", n->op->name);
164 xfprintf (F, DEFAULT_NODE_ATTR);
167 xfprintf (F, "\"%I\" color: blue ", n->op->name);
168 xfprintf (F, DEFAULT_NODE_ATTR);
171 xfprintf (F, "\"%I\" color: lightyellow ", n->op->name);
172 xfprintf (F, DEFAULT_NODE_ATTR);
175 xfprintf (F, "\"%I%I\" color: green", n->op->name, n->mode->name);
176 if (n->mode->code == irm_M)
177 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
179 xfprintf (F, DEFAULT_NODE_ATTR);
182 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, n->mode->name);
183 xfprintf (F, DEFAULT_NODE_ATTR);
186 xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
187 xfprintf (F, DEFAULT_NODE_ATTR);
190 if (n->in[1]->op->code == iro_Cmp) {
191 xfprintf (F, "\"%I%I %s\" color: yellow", n->op->name, n->mode->name,
192 get_pnc_string(n->attr.proj));
194 xfprintf (F, "\"%I%I %ld\"", n->op->name, n->mode->name, n->attr.proj);
196 xfprintf (F, DEFAULT_NODE_ATTR);
199 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
200 xfprintf (F, DEFAULT_NODE_ATTR);
203 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
204 xfprintf (F, DEFAULT_NODE_ATTR);
207 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
208 xfprintf (F, DEFAULT_NODE_ATTR);
211 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
212 xfprintf (F, DEFAULT_NODE_ATTR);
215 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
216 xfprintf (F, DEFAULT_NODE_ATTR);
219 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
220 xfprintf (F, DEFAULT_NODE_ATTR);
223 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
224 xfprintf (F, DEFAULT_NODE_ATTR);
227 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
228 xfprintf (F, DEFAULT_NODE_ATTR);
231 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
232 xfprintf (F, DEFAULT_NODE_ATTR);
235 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
236 xfprintf (F, DEFAULT_NODE_ATTR);
239 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
240 xfprintf (F, DEFAULT_NODE_ATTR);
243 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
244 xfprintf (F, DEFAULT_NODE_ATTR);
247 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
248 xfprintf (F, DEFAULT_NODE_ATTR);
251 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
252 xfprintf (F, DEFAULT_NODE_ATTR);
255 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
256 xfprintf (F, DEFAULT_NODE_ATTR);
259 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
260 xfprintf (F, DEFAULT_NODE_ATTR);
263 xfprintf (F, "\"%I\"", n->op->name);
264 xfprintf (F, DEFAULT_NODE_ATTR);
267 xfprintf (F, "\"%I\"", n->op->name);
268 xfprintf (F, DEFAULT_NODE_ATTR);
271 xfprintf (F, "\"%I\"", n->op->name);
272 xfprintf (F, DEFAULT_NODE_ATTR);
275 xfprintf (F, "\"%I\"", n->op->name);
276 xfprintf (F, DEFAULT_NODE_ATTR);
279 xfprintf (F, "\"%I%I\"", n->op->name, n->mode->name);
280 xfprintf (F, DEFAULT_NODE_ATTR);
284 xfprintf (F, "\"%R\"", n);
285 xfprintf (F, DEFAULT_NODE_ATTR);
288 xfprintf (F, "\"%I\" ", n->op->name);
289 xfprintf (F, DEFAULT_NODE_ATTR);
292 assert(get_kind(get_Sel_entity(n)) == k_entity);
293 xfprintf (F, "\"%I ", n->op->name);
294 xfprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
295 /* xdoesn't work for some reason.
296 fprintf (F, "\"%I %I\" ", n->op->name, get_entity_ident(get_Sel_entity(n))); */
297 xfprintf (F, DEFAULT_NODE_ATTR);
300 assert(get_kind(get_SymConst_type(n)) == k_type_class);
301 assert(get_class_ident((type_class *)get_SymConst_type(n)));
302 xfprintf (F, "\"%s ",
303 id_to_str(get_class_ident((type_class *)get_SymConst_type(n))));
304 switch (n->attr.i.num){
306 xfprintf (F, "tag\" ");
309 xfprintf (F, "size\" ");
315 xfprintf (F, DEFAULT_NODE_ATTR);
318 xfprintf (F, "\"%I\" ", n->op->name);
319 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
322 xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
323 xfprintf (F, DEFAULT_NODE_ATTR);
326 xfprintf (F, "\"%I%I\" ", n->op->name, n->mode->name);
328 xfprintf (F, "}\n"); /* footer */
332 /* dump the edge to the block this node belongs to */
334 dump_ir_block_edge(ir_node *n) {
336 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
337 BLOCK_EDGE_ATTR "}\n", n, get_nodes_Block(n));
341 /* dump edges to our inputs */
343 dump_ir_data_edges(ir_node *n) {
346 for (i = 0; i < get_irn_arity(n); i++) {
347 assert(get_irn_n(n, i));
348 xfprintf (F, "edge: {sourcename: \"%p\" targetname: \"%p\"",
350 fprintf (F, " label: \"%d\"", i+1);
355 /* dumps the edges between nodes and their type or entity attributes. */
356 void dump_node2type_edges (ir_node *n, void *env)
360 switch (get_irn_opcode(n)) {
362 if ( (get_SymConst_kind(n) == type_tag)
363 || (get_SymConst_kind(n) == size))
364 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
365 NODE2TYPE_EDGE_ATTR "}\n", n, get_SymConst_type(n));
368 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
369 NODE2TYPE_EDGE_ATTR "}\n", n, get_Sel_entity(n));
372 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
373 NODE2TYPE_EDGE_ATTR "}\n", n, get_Call_type(n));
376 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
377 NODE2TYPE_EDGE_ATTR "}\n", n, get_Alloc_type(n));
380 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
381 NODE2TYPE_EDGE_ATTR "}\n", n, get_Free_type(n));
389 /* dumps a type or entity and it's edges. */
391 dump_type_info (type_or_ent *tore, void *env) {
392 int i = 0; /* to shutup gcc */
394 /* dump this type or entity */
395 xfprintf (F, "node: {title: \"%p\" ", tore);
396 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
397 xfprintf (F, "label: ");
399 switch (get_kind(tore)) {
402 entity *ent = (entity *)tore;
403 xfprintf (F, "\"ent %I\"}\n", get_entity_ident(ent));
404 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
406 TYPE_EDGE_ATTR "}\n", tore, get_entity_owner(ent));
407 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
409 TYPE_EDGE_ATTR "}\n", tore, get_entity_type(ent));
413 type_class *type = (type_class *)tore;
414 xfprintf (F, "\"class %I\"}\n", get_class_ident(type));
415 for (i=0; i < get_class_n_supertype(type); i++)
416 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
417 " label: \"supertype\" " TYPE_EDGE_ATTR "}\n",
418 type, get_class_supertype(type, i));
422 type_strct *type = (type_strct *)tore;
423 xfprintf (F, "\"strct %I\"}\n", get_strct_ident(type));
427 type_method *type = (type_method *)tore;
428 xfprintf (F, "\"meth %I\"}\n", get_method_ident(type));
429 for (i = 0; i < get_method_arity(type); i++)
430 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
431 " label: \"param %d\" " TYPE_EDGE_ATTR "}\n",
432 tore, get_method_param_type(type, i), i);
433 for (i = 0; i < get_method_n_res(type); i++)
434 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
435 " label: \"res %d\" " TYPE_EDGE_ATTR "}\n",
436 tore, get_method_res_type(type, i), i);
440 type_union *type = (type_union *)tore;
441 xfprintf (F, "\"union %I\"}\n", get_union_ident(type));
446 type_array *type = (type_array *)tore;
447 xfprintf (F, "\"array %I\"}\n", get_array_ident(type));
448 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
449 TYPE_EDGE_ATTR "}\n", tore, get_array_element_type(type), i);
451 case k_type_enumeration:
453 type_enumeration *type = (type_enumeration *)tore;
454 xfprintf (F, "\"enum %I\"}\n", get_enumeration_ident(type));
458 type_pointer *type = (type_pointer *)tore;
459 xfprintf (F, "\"ptr %I\"}\n", get_pointer_ident(type));
460 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
461 TYPE_EDGE_ATTR "}\n", tore,
462 get_pointer_points_to_type(type), i);
464 case k_type_primitive:
466 type_primitive *type = (type_primitive *)tore;
467 xfprintf (F, "\"prim %I, mode %I\"}\n", get_primitive_ident(type),
468 get_mode_ident(get_primitive_mode(type)));
472 xfprintf (F, "\" faulty type \"}\n");
473 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
478 /************************************************************************/
479 /* open and close vcg file */
480 /************************************************************************/
482 void vcg_open (ir_graph *irg, char *suffix) {
483 char *fname; /* filename to put the vcg information in */
488 /** open file for vcg graph */
489 id = get_entity_ld_name (get_irg_ent(irg));
490 len = id_to_strlen (id);
493 fname = malloc (len + 5 + strlen(suffix));
494 strncpy (fname, cp, len); /* copy the filename */
496 strcat (fname, suffix); /* append file suffix */
498 fname = malloc (len + 5 + strlen(suffix));
499 strncpy (fname, cp, len); /* copy the filename */
500 fname[len] = '\0'; /* ensure string termination */
501 /*strcpy (fname, cp); * copy the filename *
502 this produces wrong, too long strings in conjuction with the
503 jocca frontend. The \0 seems to be missing. */
504 strcat (fname, suffix); /* append file suffix */
505 strcat (fname, ".vcg"); /* append the .vcg suffix */
506 F = fopen (fname, "w"); /* open file for writing */
508 panic ("cannot open %s for writing (%m)", fname); /* not reached */
513 "graph: { title: \"ir graph of %s\"\n"
514 "display_edge_labels: yes\n"
515 "layoutalgorithm: mindepth\n"
516 "manhattan_edges: yes\n"
518 "orientation: bottom_to_top\n"
519 "classname 1: \"Data\"\n"
520 "classname 2: \"Block\"\n", cp);
522 xfprintf (F, "\n"); /* a separator */
525 void vcg_open_name (const char *name) {
526 char *fname; /* filename to put the vcg information in */
529 /** open file for vcg graph */
531 fname = malloc (len + 5);
532 strcpy (fname, name); /* copy the filename */
533 strcat (fname, ".vcg"); /* append the .vcg suffix */
534 F = fopen (fname, "w"); /* open file for writing */
536 panic ("cannot open %s for writing (%m)", fname); /* not reached */
541 "graph: { title: \"ir graph of %s\"\n"
542 "display_edge_labels: yes\n"
543 "layoutalgorithm: mindepth\n"
544 "manhattan_edges: yes\n"
546 "orientation: bottom_to_top\n"
547 "classname 1: \"Data\"\n"
548 "classname 2: \"Block\"\n", name);
550 xfprintf (F, "\n"); /* a separator */
555 xfprintf (F, "}\n"); /* print footer */
556 fclose (F); /* close vcg file */
559 /************************************************************************/
560 /* routines to dump a graph, blocks as conventional nodes. */
561 /************************************************************************/
564 dump_whole_node (ir_node *n, void* env) {
566 dump_ir_block_edge(n);
567 dump_ir_data_edges(n);
571 dump_ir_graph (ir_graph *irg)
574 rem = current_ir_graph;
575 current_ir_graph = irg;
579 /* walk over the graph */
580 irg_walk(irg->end, dump_whole_node, NULL, NULL);
584 current_ir_graph = rem;
587 /***********************************************************************/
588 /* the following routines dump the nodes as attached to the blocks. */
589 /***********************************************************************/
592 dump_ir_blocks_nodes (ir_node *n, void *env) {
593 ir_node *block = (ir_node *)env;
595 if (is_no_Block(n) && get_nodes_Block(n) == block) {
597 dump_ir_data_edges(n);
602 dump_ir_block (ir_node *block, void *env) {
603 ir_graph *irg = (ir_graph *)env;
605 if (get_irn_opcode(block) == iro_Block) {
607 /* This is a block. So dump the vcg information to make a block. */
608 xfprintf(F, "graph: { title: \"%p\" label: \"", block);
610 xfprintf (F, "%ld", get_irn_node_nr(block));
612 xfprintf (F, "%I", block->op->name);
614 xfprintf(F, "\" status:clustered color:lightyellow \n");
615 /* dump the blocks edges */
616 dump_ir_data_edges(block);
618 /* dump the nodes that go into the block */
619 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
621 /* Close the vcg information for the block */
622 xfprintf(F, "}\n\n");
627 dump_ir_block_graph (ir_graph *irg)
630 rem = current_ir_graph;
631 current_ir_graph = irg;
635 /* walk over the blocks in the graph */
636 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
639 current_ir_graph = rem;
643 /***********************************************************************/
644 /* the following routines dump a control flow graph */
645 /***********************************************************************/
649 dump_block_to_cfg (ir_node *block, void *env) {
653 if (get_irn_opcode(block) == iro_Block) {
654 /* This is a block. Dump a node for the block. */
655 xfprintf (F, "node: {title: \"%p\" label: \"%I\"}", block,
658 for ( i = 0; i < get_Block_n_cfgpreds(block); i++) {
659 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
660 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" }\n",
667 dump_cfg (ir_graph *irg)
669 vcg_open (irg, "-cfg");
671 /* walk over the blocks in the graph */
672 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
678 /***********************************************************************/
679 /* the following routine dumps all type information reachable from an */
681 /***********************************************************************/
685 dump_type_graph (ir_graph *irg)
688 rem = current_ir_graph;
689 current_ir_graph = irg;
691 vcg_open (irg, "-type");
693 /* walk over the blocks in the graph */
694 type_walk_irg(irg, dump_type_info, NULL, NULL);
697 current_ir_graph = rem;
700 /***********************************************************************/
701 /* the following routine dumps all type information */
702 /***********************************************************************/
706 dump_all_types (void)
708 vcg_open_name ("All_types");
709 type_walk(dump_type_info, NULL, NULL);
713 /***********************************************************************/
714 /* dumps a graph with type information */
715 /***********************************************************************/
719 dump_ir_graph_w_types (ir_graph *irg)
722 rem = current_ir_graph;
723 current_ir_graph = irg;
725 vcg_open (irg, "-all");
727 /* dump common ir graph */
728 /* irg_block_walk(irg->end, dump_ir_block, NULL, irg); */
729 irg_walk(irg->end, dump_whole_node, NULL, NULL);
731 type_walk_irg(irg, dump_type_info, NULL, NULL);
732 /* dump edges from graph to type info */
733 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
736 current_ir_graph = rem;
739 /***********************************************************************/
740 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
742 /* dump_ir_block_graph */
744 /* dump_type_graph */
745 /* dump_ir_graph_w_types */
746 /***********************************************************************/
747 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
749 for (i=0; i < get_irp_n_irgs(); i++) {
750 dump_graph(get_irp_irg(i));