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"
37 /* Attributes of nodes */
38 #define DEFAULT_NODE_ATTR ""
39 #define DEFAULT_TYPE_ATTRIBUTE ""
41 /* Attributes of edges between Firm nodes */
42 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
43 #define CF_EDGE_ATTR "color: red"
44 #define MEM_EDGE_ATTR "color: blue"
45 #define DOMINATOR_EDGE_ATTR "color: red"
47 /* Attributes of edges between Firm nodes and type/entity nodes */
48 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
50 /* Attributes of edges in type/entity graphs. */
51 #define TYPE_METH_NODE_ATTR "color: lightyellow"
52 #define TYPE_CLASS_NODE_ATTR "color: green"
53 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
54 #define ENTITY_NODE_ATTR "color: yellow"
55 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
56 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
57 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
58 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
59 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: blue"
60 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
61 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
62 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
63 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
64 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
65 #define ENT_VALUE_EDGE_ATTR "label: \"value "
66 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
67 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
70 #if DEBUG_libfirm && NODEID_AS_LABEL
71 #define PRINT_NODEID(X) fprintf(F, "%ld", get_irn_node_nr(X))
73 #define PRINT_NODEID(X) fprintf(F, "%p", X)
76 /* A suffix to manipulate the file name. */
77 char *dump_file_suffix = NULL;
82 /* A compiler option to turn off edge labels */
84 /* A compiler option to turn off dumping values of constant entities */
85 int const_entities = 1;
86 /* A compiler option to dump the keep alive edges */
87 int dump_keepalive = 0;
88 /* A compiler option to dump the out edges in dump_ir_graph */
89 int dump_out_edge_flag = 0;
90 int dump_dominator_information_flag = 0;
92 /* A global variable to record output of the Bad node. */
96 void dump_ir_blocks_nodes (ir_node *n, void *env);
97 void dump_whole_node (ir_node *n, void* env);
99 /*******************************************************************/
100 /* routines to dump information about a single node */
101 /*******************************************************************/
106 dump_node_opcode (ir_node *n)
111 if (n->op->code == iro_Const) {
112 xfprintf (F, "%v", n->attr.con);
115 } else if (n->op->code == iro_SymConst) {
116 if (get_SymConst_kind(n) == linkage_ptr_info) {
117 /* don't use get_SymConst_ptr_info as it mangles the name. */
118 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
120 assert(get_kind(get_SymConst_type(n)) == k_type);
121 assert(get_type_ident(get_SymConst_type(n)));
122 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
123 if (get_SymConst_kind == type_tag)
126 xfprintf (F, "size");
130 } else if (n->op->code == iro_Filter && !interprocedural_view) {
135 xfprintf (F, "%I", get_irn_opident(n));
140 dump_node_mode (ir_node *n)
142 switch (n->op->code) {
160 xfprintf (F, "%I", get_mode_ident(n->mode));
167 dump_node_nodeattr (ir_node *n)
169 switch (n->op->code) {
171 if (n->in[1]->op->code == iro_Cmp) {
172 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
174 xfprintf (F, "%ld", n->attr.proj);
178 xfprintf (F, "%ld", n->attr.filter.proj);
181 assert(get_kind(get_Sel_entity(n)) == k_entity);
182 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
189 dump_node_vcgattr (ir_node *n)
191 switch (n->op->code) {
198 xfprintf (F, "color: blue");
201 xfprintf (F, "color: lightyellow");
204 xfprintf (F, "color: green");
210 xfprintf (F, "color: yellow");
213 xfprintf (F, DEFAULT_NODE_ATTR);
218 dump_node (ir_node *n) {
221 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
226 dump_node_nodeattr(n);
228 xfprintf (F, " %ld", get_irn_node_nr(n));
231 dump_node_vcgattr(n);
236 dump_ir_node (ir_node *n)
239 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
241 switch (n->op->code) { /* node label */
243 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
244 xfprintf (F, DEFAULT_NODE_ATTR);
251 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
252 xfprintf (F, DEFAULT_NODE_ATTR);
255 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
256 xfprintf (F, DEFAULT_NODE_ATTR);
259 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
260 if (get_irn_modecode(n) == irm_M)
261 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
263 xfprintf (F, DEFAULT_NODE_ATTR);
266 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
267 xfprintf (F, DEFAULT_NODE_ATTR);
270 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
271 xfprintf (F, DEFAULT_NODE_ATTR);
274 if (n->in[1]->op->code == iro_Cmp) {
275 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
276 get_pnc_string(n->attr.proj));
278 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
280 xfprintf (F, DEFAULT_NODE_ATTR);
283 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.filter.proj);
284 xfprintf (F, DEFAULT_NODE_ATTR);
287 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
288 xfprintf (F, DEFAULT_NODE_ATTR);
291 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
292 xfprintf (F, DEFAULT_NODE_ATTR);
295 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
296 xfprintf (F, DEFAULT_NODE_ATTR);
299 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
300 xfprintf (F, DEFAULT_NODE_ATTR);
303 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
304 xfprintf (F, DEFAULT_NODE_ATTR);
307 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
308 xfprintf (F, DEFAULT_NODE_ATTR);
311 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
312 xfprintf (F, DEFAULT_NODE_ATTR);
315 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
316 xfprintf (F, DEFAULT_NODE_ATTR);
319 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
320 xfprintf (F, DEFAULT_NODE_ATTR);
323 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
324 xfprintf (F, DEFAULT_NODE_ATTR);
327 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
328 xfprintf (F, DEFAULT_NODE_ATTR);
331 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
332 xfprintf (F, DEFAULT_NODE_ATTR);
335 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
336 xfprintf (F, DEFAULT_NODE_ATTR);
339 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
340 xfprintf (F, DEFAULT_NODE_ATTR);
343 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
344 xfprintf (F, DEFAULT_NODE_ATTR);
347 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
348 xfprintf (F, DEFAULT_NODE_ATTR);
351 xfprintf (F, "\"%I\"", get_irn_opident(n));
352 xfprintf (F, DEFAULT_NODE_ATTR);
355 xfprintf (F, "\"%I\"", get_irn_opident(n));
356 xfprintf (F, DEFAULT_NODE_ATTR);
359 xfprintf (F, "\"%I\"", get_irn_opident(n));
360 xfprintf (F, DEFAULT_NODE_ATTR);
363 xfprintf (F, "\"%I\"", get_irn_opident(n));
364 xfprintf (F, DEFAULT_NODE_ATTR);
367 xfprintf (F, "\"%I\"", get_irn_opident(n));
368 xfprintf (F, DEFAULT_NODE_ATTR);
371 xfprintf (F, "\"%I\"", get_irn_opident(n));
372 xfprintf (F, DEFAULT_NODE_ATTR);
375 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
376 xfprintf (F, DEFAULT_NODE_ATTR);
380 xfprintf (F, "\"%R\"", n);
381 xfprintf (F, DEFAULT_NODE_ATTR);
384 xfprintf (F, "\"%I\" ", get_irn_opident(n));
385 xfprintf (F, DEFAULT_NODE_ATTR);
388 assert(get_kind(get_Sel_entity(n)) == k_entity);
389 xfprintf (F, "\"%I ", get_irn_opident(n));
390 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
391 xfprintf (F, DEFAULT_NODE_ATTR);
394 assert(get_kind(get_SymConst_type(n)) == k_type);
395 assert(get_type_ident(get_SymConst_type(n)));
396 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
397 switch (n->attr.i.num){
399 xfprintf (F, "tag\" ");
402 xfprintf (F, "size\" ");
408 xfprintf (F, DEFAULT_NODE_ATTR);
411 xfprintf (F, "\"%I\" ", get_irn_opident(n));
412 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
415 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
416 xfprintf (F, DEFAULT_NODE_ATTR);
419 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
420 xfprintf (F, DEFAULT_NODE_ATTR);
423 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
425 xfprintf (F, "}\n"); /* footer */
429 /* dump the edge to the block this node belongs to */
431 dump_ir_block_edge(ir_node *n) {
432 if (is_no_Block(n)) {
433 xfprintf (F, "edge: { sourcename: \"");
435 xfprintf (F, "\" targetname: \"");
436 PRINT_NODEID(get_nodes_Block(n));
437 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
441 void print_edge_vcgattr(ir_node *from, int to) {
444 switch (get_irn_opcode(from)) {
446 xfprintf (F, CF_EDGE_ATTR);
448 case iro_Start: break;
451 if (get_irn_mode(get_End_keepalive(from, to)) == mode_R)
452 xfprintf (F, CF_EDGE_ATTR);
453 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
454 xfprintf (F, MEM_EDGE_ATTR);
457 case iro_EndReg: break;
458 case iro_EndExcept: break;
460 case iro_Break: break;
461 case iro_Cond: break;
464 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
466 case iro_Const: break;
467 case iro_SymConst:break;
470 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
472 case iro_CallBegin: break;
475 case iro_Minus: break;
481 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
489 case iro_Shrs: break;
492 case iro_Conv: break;
494 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
500 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
503 xfprintf (F, MEM_EDGE_ATTR);
505 case iro_Tuple: break;
508 switch (get_irn_modecode(from)) {
510 xfprintf (F, CF_EDGE_ATTR);
513 xfprintf (F, MEM_EDGE_ATTR);
519 case iro_Unknown: break;
525 /* dump edges to our inputs */
527 dump_ir_data_edges(ir_node *n) {
528 int i, visited = get_irn_visited(n);
530 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
533 for (i = 0; i < get_irn_arity(n); i++) {
534 ir_node * pred = get_irn_n(n, i);
536 if (interprocedural_view && get_irn_visited(pred) < visited) continue; /* pred not dumped */
537 fprintf (F, "edge: {sourcename: \"");
539 fprintf (F, "\" targetname: \"");
542 fprintf (F, " label: \"%d\" ", i);
543 print_edge_vcgattr(n, i);
550 dump_out_edge (ir_node *n, void* env) {
552 for (i = 0; i < get_irn_n_outs(n); i++) {
553 assert(get_irn_out(n, i));
554 fprintf (F, "edge: {sourcename: \"");
556 fprintf (F, "\" targetname: \"");
557 PRINT_NODEID(get_irn_out(n, i));
558 fprintf (F, "\" color: red linestyle: dashed");
564 /* dumps the edges between nodes and their type or entity attributes. */
565 void dump_node2type_edges (ir_node *n, void *env)
569 switch (get_irn_opcode(n)) {
571 /* @@@ some consts have an entity */
574 if ( (get_SymConst_kind(n) == type_tag)
575 || (get_SymConst_kind(n) == size)) {
576 xfprintf (F, "edge: { sourcename: \"");
578 fprintf (F, "\" targetname: \"%p\" "
579 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
583 xfprintf (F, "edge: { sourcename: \"");
585 fprintf (F, "\" targetname: \"%p\" "
586 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
589 xfprintf (F, "edge: { sourcename: \"");
591 fprintf (F, "\" targetname: \"%p\" "
592 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
595 xfprintf (F, "edge: { sourcename: \"");
597 fprintf (F, "\" targetname: \"%p\" "
598 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
601 xfprintf (F, "edge: { sourcename: \"");
603 fprintf (F, "\" targetname: \"%p\" "
604 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
612 void dump_const_expression(ir_node *value) {
613 ir_graph *rem = current_ir_graph;
614 current_ir_graph = get_const_code_irg();
615 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
616 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
617 current_ir_graph = rem;
621 void print_type_info(type *tp) {
622 if (get_type_state(tp) == layout_undefined) {
623 xfprintf(F, "state: layout_undefined\n");
625 xfprintf(F, "state: layout_fixed,\n");
627 if (get_type_mode(tp))
628 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
629 xfprintf(F, "size: %dB,\n", get_type_size(tp));
633 void print_typespecific_info(type *tp) {
634 switch (get_type_tpop_code(tp)) {
637 if(existent == get_class_peculiarity(tp))
638 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
640 xfprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
644 xfprintf (F, " " TYPE_METH_NODE_ATTR);
655 case tpo_enumeration:
668 void print_type_node(type *tp) {
669 xfprintf (F, "node: {title: \"%p\" ", tp);
670 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
671 xfprintf (F, "info1: \"");
674 print_typespecific_info(tp);
678 /* dumps a type or entity and it's edges. */
680 dump_type_info (type_or_ent *tore, void *env) {
681 int i = 0; /* to shutup gcc */
683 /* dump this type or entity */
685 switch (get_kind(tore)) {
688 entity *ent = (entity *)tore;
691 xfprintf (F, "node: {title: \"%p\" ", tore);
692 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
693 xfprintf (F, "label: ");
694 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
695 if(dynamic_allocated == get_entity_allocation(ent))
696 xfprintf (F, " info1:\"dynamic allocated\n");
698 xfprintf (F, " info1:\"static allocated\n");
699 switch (get_entity_visibility(ent)) {
700 case local: fprintf (F, "local\n"); break;
701 case external_visible: fprintf (F, "external_visible\n"); break;
702 case external_allocated: fprintf (F, "external_allocate\n");break;
704 switch (get_entity_variability(ent)) {
705 case uninitialized: fprintf (F, "uninitialized");break;
706 case initialized: fprintf (F, "initialized"); break;
707 case part_constant: fprintf (F, "part_constant");break;
708 case constant: fprintf (F, "constant"); break;
710 if (is_method_type(get_entity_type(ent)))
711 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
712 xfprintf(F, "\"}\n");
714 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
715 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
716 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
717 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
718 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
719 if(is_class_type(get_entity_owner(ent))) {
720 for(i = 0; i < get_entity_n_overwrites(ent); i++)
721 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
722 ENT_OVERWRITES_EDGE_ATTR "}\n",
723 ent, get_entity_overwrites(ent, i));
725 /* attached subgraphs */
726 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
727 if (is_atomic_entity(ent)) {
728 value = get_atomic_ent_value(ent);
729 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
731 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
732 dump_const_expression(value);
734 if (is_compound_entity(ent)) {
735 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
736 value = get_compound_ent_value(ent, i);
737 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
739 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
740 dump_const_expression(value);
741 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
742 ENT_CORR_EDGE_ATTR "}\n", ent,
743 get_compound_ent_value_member(ent, i), i);
750 type *tp = (type *)tore;
752 /* and now the edges */
753 switch (get_type_tpop_code(tp)) {
756 for (i=0; i < get_class_n_supertype(tp); i++)
757 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
758 TYPE_SUPER_EDGE_ATTR "}\n",
759 tp, get_class_supertype(tp, i));
760 for (i=0; i < get_class_n_member(tp); i++)
761 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
762 TYPE_MEMBER_EDGE_ATTR "}\n",
763 tp, get_class_member(tp, i));
767 for (i=0; i < get_struct_n_member(tp); i++)
768 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
769 TYPE_MEMBER_EDGE_ATTR "}\n",
770 tp, get_struct_member(tp, i));
774 for (i = 0; i < get_method_n_params(tp); i++)
775 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
776 METH_PAR_EDGE_ATTR "}\n",
777 tp, get_method_param_type(tp, i), i);
778 for (i = 0; i < get_method_n_res(tp); i++)
779 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
780 METH_RES_EDGE_ATTR "}\n",
781 tp, get_method_res_type(tp, i), i);
785 for (i = 0; i < get_union_n_members(tp); i++)
786 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
787 "label: \"\"f" UNION_EDGE_ATTR "}\n",
788 tp, get_union_member(tp, i));
792 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
793 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
794 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
795 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
797 case tpo_enumeration:
802 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
803 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
804 get_pointer_points_to_type(tp), i);
812 break; /* case k_type */
815 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
817 } /* switch kind_or_entity */
820 /************************************************************************/
821 /* open and close vcg file */
822 /************************************************************************/
824 void vcg_open (ir_graph *irg, char *suffix) {
825 char *fname; /* filename to put the vcg information in */
832 /** open file for vcg graph */
833 ent = get_irg_ent(irg);
834 id = ent->ld_name ? ent->ld_name : ent->name;
835 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
836 len = id_to_strlen (id);
838 if (dump_file_suffix)
839 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
841 fname = malloc (len + 5 + strlen(suffix));
842 strncpy (fname, cp, len); /* copy the filename */
844 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
845 strcat (fname, suffix); /* append file suffix */
846 strcat (fname, ".vcg"); /* append the .vcg suffix */
847 F = fopen (fname, "w"); /* open file for writing */
849 panic ("cannot open %s for writing (%m)", fname); /* not reached */
853 strcpy(label, "yes");
855 strcpy (label, "no");
860 "graph: { title: \"ir graph of %s\"\n"
861 "display_edge_labels: %s\n"
862 "layoutalgorithm: mindepth\n"
863 "manhattan_edges: yes\n"
865 "orientation: bottom_to_top\n"
866 "classname 1: \"Data\"\n"
867 "classname 2: \"Block\"\n"
868 "classname 3: \"Entity type\""
869 "classname 4: \"Entity owner\""
870 "classname 5: \"Method Param\""
871 "classname 6: \"Method Res\""
872 "classname 7: \"Super\""
873 "classname 8: \"Union\""
874 "classname 9: \"Points-to\""
875 "classname 10: \"Array Element Type\""
876 "classname 11: \"Overwrites\""
877 "classname 12: \"Member\""
880 xfprintf (F, "\n"); /* a separator */
883 void vcg_open_name (const char *name) {
884 char *fname; /* filename to put the vcg information in */
888 /** open file for vcg graph */
890 fname = malloc (len + 5);
891 strcpy (fname, name); /* copy the filename */
892 strcat (fname, ".vcg"); /* append the .vcg suffix */
893 F = fopen (fname, "w"); /* open file for writing */
895 panic ("cannot open %s for writing (%m)", fname); /* not reached */
899 strcpy(label, "yes");
901 strcpy (label, "no");
906 "graph: { title: \"ir graph of %s\"\n"
907 "display_edge_labels: %s\n"
908 "layoutalgorithm: mindepth\n"
909 "manhattan_edges: yes\n"
911 "orientation: bottom_to_top\n"
912 "classname 1: \"Data\"\n"
913 "classname 2: \"Block\"\n"
914 "classname 3: \"Entity type\"\n"
915 "classname 4: \"Entity owner\"\n"
916 "classname 5: \"Method Param\"\n"
917 "classname 6: \"Method Res\"\n"
918 "classname 7: \"Super\"\n"
919 "classname 8: \"Union\"\n"
920 "classname 9: \"Points-to\"\n"
921 "classname 10: \"Array Element Type\"\n"
922 "classname 11: \"Overwrites\"\n"
923 "classname 12: \"Member\"\n"
926 xfprintf (F, "\n"); /* a separator */
931 xfprintf (F, "}\n"); /* print footer */
932 fclose (F); /* close vcg file */
935 /************************************************************************/
936 /* routines to dump a graph, blocks as conventional nodes. */
937 /************************************************************************/
939 int node_floats(ir_node *n) {
941 return ((get_op_pinned(get_irn_op(n)) == floats) &&
942 (get_irg_pinned(current_ir_graph) == floats));
946 dump_whole_node (ir_node *n, void* env) {
948 if (!node_floats(n)) dump_ir_block_edge(n);
949 dump_ir_data_edges(n);
953 dump_ir_graph (ir_graph *irg)
956 rem = current_ir_graph;
957 current_ir_graph = irg;
961 /* walk over the graph */
962 /* dump_whole_node must be called in post visiting predecessors */
963 irg_walk(irg->end, NULL, dump_whole_node, NULL);
965 /* dump the out edges in a separate walk */
966 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
967 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
972 current_ir_graph = rem;
975 /***********************************************************************/
976 /* the following routines dump the nodes as attached to the blocks. */
977 /***********************************************************************/
980 dump_ir_blocks_nodes (ir_node *n, void *env) {
981 ir_node *block = (ir_node *)env;
983 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
985 dump_ir_data_edges(n);
987 if (get_irn_op(n) == op_Bad)
992 dump_ir_block (ir_node *block, void *env) {
993 ir_graph *irg = (ir_graph *)env;
995 if (get_irn_opcode(block) == iro_Block) {
997 /* This is a block. So dump the vcg information to make a block. */
998 xfprintf(F, "graph: { title: \"");
1000 fprintf(F, "\" label: \"");
1001 #ifdef DEBUG_libfirm
1002 xfprintf (F, "%ld", get_irn_node_nr(block));
1004 xfprintf (F, "%I", block->op->name);
1006 if (exc_normal != get_Block_exc (block))
1007 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1009 xfprintf(F, "\" status:clustered color:%s \n",
1010 get_Block_matured (block) ? "yellow" : "red");
1011 /* dump the blocks edges */
1012 dump_ir_data_edges(block);
1014 /* dump the nodes that go into the block */
1015 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1017 /* Close the vcg information for the block */
1018 xfprintf(F, "}\n\n");
1024 dump_blockless_nodes (ir_node *n, void *env) {
1025 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1027 dump_ir_data_edges(n);
1028 dump_ir_block_edge(n);
1029 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1032 if (node_floats(n)) {
1034 dump_ir_data_edges(n);
1035 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1039 void dump_ir_block_graph_2 (ir_graph *irg)
1042 /* walk over the blocks in the graph */
1043 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1045 /* dump all nodes that are not in a Block */
1046 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1048 /* dump the Bad node */
1050 dump_node(get_irg_bad(irg));
1054 dump_ir_block_graph (ir_graph *irg)
1057 rem = current_ir_graph;
1058 current_ir_graph = irg;
1062 dump_ir_block_graph_2 (irg);
1065 current_ir_graph = rem;
1069 /***********************************************************************/
1070 /* the following routines dump a control flow graph */
1071 /***********************************************************************/
1075 dump_block_to_cfg (ir_node *block, void *env) {
1079 if (get_irn_opcode(block) == iro_Block) {
1080 /* This is a block. Dump a node for the block. */
1081 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1082 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1084 if (exc_normal != get_Block_exc (block))
1085 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1087 xfprintf (F, "\" ");
1088 if (dump_dominator_information_flag)
1089 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1090 xfprintf (F, "}\n");
1091 /* Dump the edges */
1092 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1093 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1094 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1095 xfprintf (F, "edge: { sourcename: \"");
1096 PRINT_NODEID(block);
1097 fprintf (F, "\" targetname: \"");
1099 fprintf (F, "\" }\n");
1102 /* Dump dominator edge */
1103 if (dump_dominator_information_flag && get_Block_idom(block)) {
1104 pred = get_Block_idom(block);
1105 xfprintf (F, "edge: { sourcename: \"");
1106 PRINT_NODEID(block);
1107 fprintf (F, "\" targetname: \"");
1109 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1115 dump_cfg (ir_graph *irg)
1117 ir_graph *rem = current_ir_graph;
1118 int ddif = dump_dominator_information_flag;
1119 current_ir_graph = irg;
1120 vcg_open (irg, "-cfg");
1122 if (get_irg_dom_state(irg) != dom_consistent)
1123 dump_dominator_information_flag = 0;
1125 /* walk over the blocks in the graph */
1126 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1127 dump_ir_node (irg->bad);
1129 dump_dominator_information_flag = ddif;
1131 current_ir_graph = rem;
1135 /***********************************************************************/
1136 /* the following routine dumps all type information reachable from an */
1138 /***********************************************************************/
1142 dump_type_graph (ir_graph *irg)
1145 rem = current_ir_graph;
1146 current_ir_graph = irg;
1148 vcg_open (irg, "-type");
1150 /* walk over the blocks in the graph */
1151 type_walk_irg(irg, dump_type_info, NULL, NULL);
1152 /* The walker for the const code can be called several times for the
1153 same (sub) experssion. So that no nodes are dumped several times
1154 we decrease the visited flag of the corresponding graph after each
1155 walk. So now increase it finally. */
1156 inc_irg_visited(get_const_code_irg());
1159 current_ir_graph = rem;
1162 /***********************************************************************/
1163 /* the following routine dumps all type information */
1164 /***********************************************************************/
1168 dump_all_types (void)
1170 vcg_open_name ("All_types");
1171 type_walk(dump_type_info, NULL, NULL);
1172 inc_irg_visited(get_const_code_irg());
1176 /***********************************************************************/
1177 /* dumps a graph with type information */
1178 /***********************************************************************/
1182 dump_ir_graph_w_types (ir_graph *irg)
1185 rem = current_ir_graph;
1186 current_ir_graph = irg;
1188 vcg_open (irg, "-all");
1190 /* dump common ir graph */
1191 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1192 /* dump type info */
1193 type_walk_irg(irg, dump_type_info, NULL, NULL);
1194 inc_irg_visited(get_const_code_irg());
1195 /* dump edges from graph to type info */
1196 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1199 current_ir_graph = rem;
1203 dump_ir_block_graph_w_types (ir_graph *irg)
1206 rem = current_ir_graph;
1207 current_ir_graph = irg;
1209 vcg_open (irg, "-all");
1211 /* dump common blocked ir graph */
1212 dump_ir_block_graph_2(irg);
1213 /* dump type info */
1214 type_walk_irg(irg, dump_type_info, NULL, NULL);
1215 inc_irg_visited(get_const_code_irg());
1216 /* dump edges from graph to type info */
1217 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1220 current_ir_graph = rem;
1223 /***********************************************************************/
1224 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1226 /* dump_ir_block_graph */
1228 /* dump_type_graph */
1229 /* dump_ir_graph_w_types */
1230 /***********************************************************************/
1231 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1233 for (i=0; i < get_irp_n_irgs(); i++) {
1234 dump_graph(get_irp_irg(i));
1239 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1240 abort with a segmentation fault. */
1241 void turn_off_edge_labels() {
1245 void turn_off_constant_entity_values() {
1249 void dump_keepalive_edges() {
1253 void dump_out_edges() {
1254 dump_out_edge_flag = 1;
1257 void dump_dominator_information() {
1258 dump_dominator_information_flag = 1;
1262 static void clear_link(ir_node * node, void * env) {
1263 set_irn_link(node, NULL);
1267 static inline bool is_Block(ir_node * node) {
1268 return !is_no_Block(node);
1272 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1274 || node_floats(node)
1275 || get_irn_op(node) == op_Bad
1276 || get_irn_op(node) == op_Unknown) {
1277 pmap_entry * entry = pmap_find(map, current_ir_graph);
1279 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1281 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1283 pmap_insert(map, current_ir_graph, arr);
1286 ir_node * block = get_nodes_Block(node);
1287 set_irn_link(node, get_irn_link(block));
1288 set_irn_link(block, node);
1293 static void dump_cg_ir_block(ir_node * node, void * env) {
1294 assert(is_Block(node));
1295 xfprintf(F, "graph: { title: \"");
1297 fprintf(F, "\" label: \"");
1298 #ifdef DEBUG_libfirm
1299 xfprintf (F, "%ld", get_irn_node_nr(node));
1301 xfprintf (F, "%I", node->op->name);
1303 if (exc_normal != get_Block_exc(node)) {
1304 fprintf (F, " (%s)", exc_to_string (get_Block_exc(node)));
1307 xfprintf(F, "\" status:clustered color:%s \n",
1308 get_Block_matured(node) ? "yellow" : "red");
1310 /* dump the blocks edges */
1311 dump_ir_data_edges(node);
1313 /* dump the nodes that go into the block */
1314 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1316 dump_ir_data_edges(node);
1319 /* Close the vcg information for the block */
1320 xfprintf(F, "}\n\n");
1324 /* dump interprocedural graph with surrounding methods */
1325 void dump_cg_block_graph(ir_graph * irg) {
1326 pmap * map = pmap_create();
1330 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1331 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1332 ir_node ** arr = entry->value;
1335 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1336 get_entity_ident(get_irg_ent(entry->key)),
1337 get_entity_ident(get_irg_ent(entry->key)));
1339 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1340 ir_node * node = arr[i];
1341 if (is_Block(node)) {
1342 dump_cg_ir_block(node, NULL);
1345 dump_ir_data_edges(node);
1351 /* Close the vcg information for the irg */
1352 xfprintf(F, "}\n\n");
1361 /* dump interprocedural block graph with surrounding methods */
1362 void dump_cg_graph(ir_graph * irg) {
1363 pmap * map = pmap_create();
1367 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1368 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1369 ir_node ** arr = entry->value;
1371 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1373 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1374 irg_ident, irg_ident);
1376 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1377 ir_node * node = arr[i];
1379 dump_ir_data_edges(node);
1380 if (is_Block(node)) {
1381 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1383 dump_ir_block_edge(node);
1384 dump_ir_data_edges(node);
1391 /* Close the vcg information for the irg */
1392 xfprintf(F, "}\n\n");