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 switch (get_entity_allocation(ent)) {
696 case dynamic_allocated: fprintf (F, " info1:\"dynamic allocated\n"); break;
697 case automatic_allocated: fprintf (F, " info1:\"automatic allocated\n"); break;
698 case static_allocated: fprintf (F, " info1:\"static allocated\n"); break;
700 switch (get_entity_visibility(ent)) {
701 case local: fprintf (F, "local\n"); break;
702 case external_visible: fprintf (F, "external_visible\n"); break;
703 case external_allocated: fprintf (F, "external_allocate\n"); break;
705 switch (get_entity_variability(ent)) {
706 case uninitialized: fprintf (F, "uninitialized\n");break;
707 case initialized: fprintf (F, "initialized\n"); break;
708 case part_constant: fprintf (F, "part_constant\n");break;
709 case constant: fprintf (F, "constant\n"); break;
711 switch (get_entity_volatility(ent)) {
712 case non_volatile: fprintf (F, "non_volatile\n"); break;
713 case is_volatile: fprintf (F, "is_volatile\n"); break;
715 switch (get_entity_peculiarity(ent)) {
716 case description: fprintf (F, "description\n"); break;
717 case inherited: fprintf (F, "inherited\n"); break;
718 case existent: fprintf (F, "existent\n"); break;
720 if (is_method_type(get_entity_type(ent)))
721 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
722 xfprintf(F, "\"}\n");
724 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
725 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
726 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
727 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
728 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
729 if(is_class_type(get_entity_owner(ent))) {
730 for(i = 0; i < get_entity_n_overwrites(ent); i++)
731 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
732 ENT_OVERWRITES_EDGE_ATTR "}\n",
733 ent, get_entity_overwrites(ent, i));
735 /* attached subgraphs */
736 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
737 if (is_atomic_entity(ent)) {
738 value = get_atomic_ent_value(ent);
739 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
741 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
742 dump_const_expression(value);
744 if (is_compound_entity(ent)) {
745 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
746 value = get_compound_ent_value(ent, i);
747 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
749 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
750 dump_const_expression(value);
751 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
752 ENT_CORR_EDGE_ATTR "}\n", ent,
753 get_compound_ent_value_member(ent, i), i);
760 type *tp = (type *)tore;
762 /* and now the edges */
763 switch (get_type_tpop_code(tp)) {
766 for (i=0; i < get_class_n_supertypes(tp); i++)
767 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
768 TYPE_SUPER_EDGE_ATTR "}\n",
769 tp, get_class_supertype(tp, i));
770 for (i=0; i < get_class_n_members(tp); i++)
771 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
772 TYPE_MEMBER_EDGE_ATTR "}\n",
773 tp, get_class_member(tp, i));
777 for (i=0; i < get_struct_n_members(tp); i++)
778 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
779 TYPE_MEMBER_EDGE_ATTR "}\n",
780 tp, get_struct_member(tp, i));
784 for (i = 0; i < get_method_n_params(tp); i++)
785 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
786 METH_PAR_EDGE_ATTR "}\n",
787 tp, get_method_param_type(tp, i), i);
788 for (i = 0; i < get_method_n_ress(tp); i++)
789 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
790 METH_RES_EDGE_ATTR "}\n",
791 tp, get_method_res_type(tp, i), i);
795 for (i = 0; i < get_union_n_members(tp); i++)
796 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
797 "label: \"\"f" UNION_EDGE_ATTR "}\n",
798 tp, get_union_member(tp, i));
802 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
803 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
804 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
805 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
807 case tpo_enumeration:
812 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
813 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
814 get_pointer_points_to_type(tp), i);
822 break; /* case k_type */
825 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
827 } /* switch kind_or_entity */
830 /************************************************************************/
831 /* open and close vcg file */
832 /************************************************************************/
834 void vcg_open (ir_graph *irg, char *suffix) {
835 char *fname; /* filename to put the vcg information in */
842 /** open file for vcg graph */
843 ent = get_irg_ent(irg);
844 id = ent->ld_name ? ent->ld_name : ent->name;
845 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
846 len = id_to_strlen (id);
848 if (dump_file_suffix)
849 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
851 fname = malloc (len + 5 + strlen(suffix));
852 strncpy (fname, cp, len); /* copy the filename */
854 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
855 strcat (fname, suffix); /* append file suffix */
856 strcat (fname, ".vcg"); /* append the .vcg suffix */
857 F = fopen (fname, "w"); /* open file for writing */
859 panic ("cannot open %s for writing (%m)", fname); /* not reached */
863 strcpy(label, "yes");
865 strcpy (label, "no");
870 "graph: { title: \"ir graph of %s\"\n"
871 "display_edge_labels: %s\n"
872 "layoutalgorithm: mindepth\n"
873 "manhattan_edges: yes\n"
875 "orientation: bottom_to_top\n"
876 "classname 1: \"Data\"\n"
877 "classname 2: \"Block\"\n"
878 "classname 3: \"Entity type\""
879 "classname 4: \"Entity owner\""
880 "classname 5: \"Method Param\""
881 "classname 6: \"Method Res\""
882 "classname 7: \"Super\""
883 "classname 8: \"Union\""
884 "classname 9: \"Points-to\""
885 "classname 10: \"Array Element Type\""
886 "classname 11: \"Overwrites\""
887 "classname 12: \"Member\""
890 xfprintf (F, "\n"); /* a separator */
893 void vcg_open_name (const char *name) {
894 char *fname; /* filename to put the vcg information in */
898 /** open file for vcg graph */
900 fname = malloc (len + 5);
901 strcpy (fname, name); /* copy the filename */
902 strcat (fname, ".vcg"); /* append the .vcg suffix */
903 F = fopen (fname, "w"); /* open file for writing */
905 panic ("cannot open %s for writing (%m)", fname); /* not reached */
909 strcpy(label, "yes");
911 strcpy (label, "no");
916 "graph: { title: \"ir graph of %s\"\n"
917 "display_edge_labels: %s\n"
918 "layoutalgorithm: mindepth\n"
919 "manhattan_edges: yes\n"
921 "orientation: bottom_to_top\n"
922 "classname 1: \"Data\"\n"
923 "classname 2: \"Block\"\n"
924 "classname 3: \"Entity type\"\n"
925 "classname 4: \"Entity owner\"\n"
926 "classname 5: \"Method Param\"\n"
927 "classname 6: \"Method Res\"\n"
928 "classname 7: \"Super\"\n"
929 "classname 8: \"Union\"\n"
930 "classname 9: \"Points-to\"\n"
931 "classname 10: \"Array Element Type\"\n"
932 "classname 11: \"Overwrites\"\n"
933 "classname 12: \"Member\"\n"
936 xfprintf (F, "\n"); /* a separator */
941 xfprintf (F, "}\n"); /* print footer */
942 fclose (F); /* close vcg file */
945 /************************************************************************/
946 /* routines to dump a graph, blocks as conventional nodes. */
947 /************************************************************************/
949 int node_floats(ir_node *n) {
951 return ((get_op_pinned(get_irn_op(n)) == floats) &&
952 (get_irg_pinned(current_ir_graph) == floats));
956 dump_whole_node (ir_node *n, void* env) {
958 if (!node_floats(n)) dump_ir_block_edge(n);
959 dump_ir_data_edges(n);
963 dump_ir_graph (ir_graph *irg)
966 rem = current_ir_graph;
967 current_ir_graph = irg;
971 /* walk over the graph */
972 /* dump_whole_node must be called in post visiting predecessors */
973 irg_walk(irg->end, NULL, dump_whole_node, NULL);
975 /* dump the out edges in a separate walk */
976 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
977 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
982 current_ir_graph = rem;
985 /***********************************************************************/
986 /* the following routines dump the nodes as attached to the blocks. */
987 /***********************************************************************/
990 dump_ir_blocks_nodes (ir_node *n, void *env) {
991 ir_node *block = (ir_node *)env;
993 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
995 dump_ir_data_edges(n);
997 if (get_irn_op(n) == op_Bad)
1002 dump_ir_block (ir_node *block, void *env) {
1003 ir_graph *irg = (ir_graph *)env;
1005 if (get_irn_opcode(block) == iro_Block) {
1007 /* This is a block. So dump the vcg information to make a block. */
1008 xfprintf(F, "graph: { title: \"");
1009 PRINT_NODEID(block);
1010 fprintf(F, "\" label: \"");
1011 #ifdef DEBUG_libfirm
1012 xfprintf (F, "%ld", get_irn_node_nr(block));
1014 xfprintf (F, "%I", block->op->name);
1016 if (exc_normal != get_Block_exc (block))
1017 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1019 xfprintf(F, "\" status:clustered color:%s \n",
1020 get_Block_matured (block) ? "yellow" : "red");
1021 /* dump the blocks edges */
1022 dump_ir_data_edges(block);
1024 /* dump the nodes that go into the block */
1025 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1027 /* Close the vcg information for the block */
1028 xfprintf(F, "}\n\n");
1034 dump_blockless_nodes (ir_node *n, void *env) {
1035 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1037 dump_ir_data_edges(n);
1038 dump_ir_block_edge(n);
1039 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1042 if (node_floats(n)) {
1044 dump_ir_data_edges(n);
1045 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1049 void dump_ir_block_graph_2 (ir_graph *irg)
1052 /* walk over the blocks in the graph */
1053 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1055 /* dump all nodes that are not in a Block */
1056 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1058 /* dump the Bad node */
1060 dump_node(get_irg_bad(irg));
1064 dump_ir_block_graph (ir_graph *irg)
1067 rem = current_ir_graph;
1068 current_ir_graph = irg;
1072 dump_ir_block_graph_2 (irg);
1075 current_ir_graph = rem;
1079 /***********************************************************************/
1080 /* the following routines dump a control flow graph */
1081 /***********************************************************************/
1085 dump_block_to_cfg (ir_node *block, void *env) {
1089 if (get_irn_opcode(block) == iro_Block) {
1090 /* This is a block. Dump a node for the block. */
1091 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1092 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1094 if (exc_normal != get_Block_exc (block))
1095 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1097 xfprintf (F, "\" ");
1098 if (dump_dominator_information_flag)
1099 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1100 xfprintf (F, "}\n");
1101 /* Dump the edges */
1102 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1103 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1104 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1105 xfprintf (F, "edge: { sourcename: \"");
1106 PRINT_NODEID(block);
1107 fprintf (F, "\" targetname: \"");
1109 fprintf (F, "\" }\n");
1112 /* Dump dominator edge */
1113 if (dump_dominator_information_flag && get_Block_idom(block)) {
1114 pred = get_Block_idom(block);
1115 xfprintf (F, "edge: { sourcename: \"");
1116 PRINT_NODEID(block);
1117 fprintf (F, "\" targetname: \"");
1119 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1125 dump_cfg (ir_graph *irg)
1127 ir_graph *rem = current_ir_graph;
1128 int ddif = dump_dominator_information_flag;
1129 current_ir_graph = irg;
1130 vcg_open (irg, "-cfg");
1132 if (get_irg_dom_state(irg) != dom_consistent)
1133 dump_dominator_information_flag = 0;
1135 /* walk over the blocks in the graph */
1136 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1137 dump_ir_node (irg->bad);
1139 dump_dominator_information_flag = ddif;
1141 current_ir_graph = rem;
1145 /***********************************************************************/
1146 /* the following routine dumps all type information reachable from an */
1148 /***********************************************************************/
1152 dump_type_graph (ir_graph *irg)
1155 rem = current_ir_graph;
1156 current_ir_graph = irg;
1158 vcg_open (irg, "-type");
1160 /* walk over the blocks in the graph */
1161 type_walk_irg(irg, dump_type_info, NULL, NULL);
1162 /* The walker for the const code can be called several times for the
1163 same (sub) experssion. So that no nodes are dumped several times
1164 we decrease the visited flag of the corresponding graph after each
1165 walk. So now increase it finally. */
1166 inc_irg_visited(get_const_code_irg());
1169 current_ir_graph = rem;
1172 /***********************************************************************/
1173 /* the following routine dumps all type information */
1174 /***********************************************************************/
1178 dump_all_types (void)
1180 vcg_open_name ("All_types");
1181 type_walk(dump_type_info, NULL, NULL);
1182 inc_irg_visited(get_const_code_irg());
1186 /***********************************************************************/
1187 /* dumps a graph with type information */
1188 /***********************************************************************/
1192 dump_ir_graph_w_types (ir_graph *irg)
1195 rem = current_ir_graph;
1196 current_ir_graph = irg;
1198 vcg_open (irg, "-all");
1200 /* dump common ir graph */
1201 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1202 /* dump type info */
1203 type_walk_irg(irg, dump_type_info, NULL, NULL);
1204 inc_irg_visited(get_const_code_irg());
1205 /* dump edges from graph to type info */
1206 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1209 current_ir_graph = rem;
1213 dump_ir_block_graph_w_types (ir_graph *irg)
1216 rem = current_ir_graph;
1217 current_ir_graph = irg;
1219 vcg_open (irg, "-all");
1221 /* dump common blocked ir graph */
1222 dump_ir_block_graph_2(irg);
1223 /* dump type info */
1224 type_walk_irg(irg, dump_type_info, NULL, NULL);
1225 inc_irg_visited(get_const_code_irg());
1226 /* dump edges from graph to type info */
1227 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1230 current_ir_graph = rem;
1233 /***********************************************************************/
1234 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1236 /* dump_ir_block_graph */
1238 /* dump_type_graph */
1239 /* dump_ir_graph_w_types */
1240 /***********************************************************************/
1241 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1243 for (i=0; i < get_irp_n_irgs(); i++) {
1244 dump_graph(get_irp_irg(i));
1249 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1250 abort with a segmentation fault. */
1251 void turn_off_edge_labels() {
1255 void turn_off_constant_entity_values() {
1259 void dump_keepalive_edges() {
1263 void dump_out_edges() {
1264 dump_out_edge_flag = 1;
1267 void dump_dominator_information() {
1268 dump_dominator_information_flag = 1;
1272 static void clear_link(ir_node * node, void * env) {
1273 set_irn_link(node, NULL);
1277 static INLINE bool is_Block(ir_node * node) {
1278 return !is_no_Block(node);
1282 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1284 || node_floats(node)
1285 || get_irn_op(node) == op_Bad
1286 || get_irn_op(node) == op_Unknown) {
1287 pmap_entry * entry = pmap_find(map, current_ir_graph);
1289 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1291 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1293 pmap_insert(map, current_ir_graph, arr);
1296 ir_node * block = get_nodes_Block(node);
1297 set_irn_link(node, get_irn_link(block));
1298 set_irn_link(block, node);
1303 static void dump_cg_ir_block(ir_node * node, void * env) {
1304 assert(is_Block(node));
1305 xfprintf(F, "graph: { title: \"");
1307 fprintf(F, "\" label: \"");
1308 #ifdef DEBUG_libfirm
1309 xfprintf (F, "%ld", get_irn_node_nr(node));
1311 xfprintf (F, "%I", node->op->name);
1313 if (exc_normal != get_Block_exc(node)) {
1314 fprintf (F, " (%s)", exc_to_string (get_Block_exc(node)));
1317 xfprintf(F, "\" status:clustered color:%s \n",
1318 get_Block_matured(node) ? "yellow" : "red");
1320 /* dump the blocks edges */
1321 dump_ir_data_edges(node);
1323 /* dump the nodes that go into the block */
1324 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1326 dump_ir_data_edges(node);
1329 /* Close the vcg information for the block */
1330 xfprintf(F, "}\n\n");
1334 /* dump interprocedural graph with surrounding methods */
1335 void dump_cg_block_graph(ir_graph * irg) {
1336 pmap * map = pmap_create();
1340 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1341 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1342 ir_node ** arr = entry->value;
1345 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1346 get_entity_ident(get_irg_ent(entry->key)),
1347 get_entity_ident(get_irg_ent(entry->key)));
1349 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1350 ir_node * node = arr[i];
1351 if (is_Block(node)) {
1352 dump_cg_ir_block(node, NULL);
1355 dump_ir_data_edges(node);
1361 /* Close the vcg information for the irg */
1362 xfprintf(F, "}\n\n");
1371 /* dump interprocedural block graph with surrounding methods */
1372 void dump_cg_graph(ir_graph * irg) {
1373 pmap * map = pmap_create();
1377 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1378 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1379 ir_node ** arr = entry->value;
1381 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1383 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1384 irg_ident, irg_ident);
1386 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1387 ir_node * node = arr[i];
1389 dump_ir_data_edges(node);
1390 if (is_Block(node)) {
1391 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1393 dump_ir_block_edge(node);
1394 dump_ir_data_edges(node);
1401 /* Close the vcg information for the irg */
1402 xfprintf(F, "}\n\n");