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 "firm_common_t.h"
38 /* Attributes of nodes */
39 #define DEFAULT_NODE_ATTR ""
40 #define DEFAULT_TYPE_ATTRIBUTE ""
42 /* Attributes of edges between Firm nodes */
43 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
44 #define CF_EDGE_ATTR "color: red"
45 #define MEM_EDGE_ATTR "color: blue"
46 #define DOMINATOR_EDGE_ATTR "color: red"
48 #define BACK_EDGE_ATTR "linestyle: dashed "
50 /* Attributes of edges between Firm nodes and type/entity nodes */
51 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
53 /* Attributes of edges in type/entity graphs. */
54 #define TYPE_METH_NODE_ATTR "color: lightyellow"
55 #define TYPE_CLASS_NODE_ATTR "color: green"
56 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
57 #define ENTITY_NODE_ATTR "color: yellow"
58 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
59 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
60 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
61 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
62 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: blue"
63 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
64 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
65 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
66 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
67 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
68 #define ENT_VALUE_EDGE_ATTR "label: \"value "
69 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
70 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
73 #if DEBUG_libfirm && NODEID_AS_LABEL
74 #define PRINT_NODEID(X) fprintf(F, "%ld", get_irn_node_nr(X))
76 #define PRINT_NODEID(X) fprintf(F, "%p", X)
79 /* A suffix to manipulate the file name. */
80 char *dump_file_suffix = NULL;
85 /* A compiler option to turn off edge labels */
87 /* A compiler option to turn off dumping values of constant entities */
88 int const_entities = 1;
89 /* A compiler option to dump the keep alive edges */
90 int dump_keepalive = 0;
91 /* Compiler options to dump analysis information in dump_ir_graph */
92 int dump_out_edge_flag = 0;
93 int dump_dominator_information_flag = 0;
94 int dump_loop_information_flag = 0;
95 int dump_const_local = 0;
96 static INLINE bool dump_const_local_set() {
97 if (!dump_out_edge_flag && !dump_loop_information_flag)
98 return dump_const_local;
103 /* A global variable to record output of the Bad node. */
106 void dump_ir_blocks_nodes (ir_node *n, void *env);
107 void dump_whole_node (ir_node *n, void* env);
109 /*******************************************************************/
110 /* routines to dump information about a single node */
111 /*******************************************************************/
116 dump_node_opcode (ir_node *n)
121 if (n->op->code == iro_Const) {
122 xfprintf (F, "%v", n->attr.con);
125 } else if (n->op->code == iro_SymConst) {
126 if (get_SymConst_kind(n) == linkage_ptr_info) {
127 /* don't use get_SymConst_ptr_info as it mangles the name. */
128 xfprintf (F, "SymC %I", n->attr.i.tori.ptrinfo);
130 assert(get_kind(get_SymConst_type(n)) == k_type);
131 assert(get_type_ident(get_SymConst_type(n)));
132 xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
133 if (get_SymConst_kind == type_tag)
136 xfprintf (F, "size");
140 } else if (n->op->code == iro_Filter && !interprocedural_view) {
145 xfprintf (F, "%I", get_irn_opident(n));
150 dump_node_mode (ir_node *n)
152 switch (n->op->code) {
170 xfprintf (F, "%I", get_mode_ident(n->mode));
176 void dump_node_loop_info(ir_node *n) {
177 // if (get_irn_loop(n))
178 // xfprintf(F, "\n in loop %d", get_loop_depth(get_irn_loop(n)));
182 dump_node_nodeattr (ir_node *n)
184 switch (n->op->code) {
186 if (false && interprocedural_view) {
187 xfprintf (F, "%I", get_entity_ident(get_irg_ent(current_ir_graph)));
191 if (n->in[1]->op->code == iro_Cmp) {
192 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
194 xfprintf (F, "%ld", n->attr.proj);
198 xfprintf (F, "%ld", n->attr.filter.proj);
201 assert(get_kind(get_Sel_entity(n)) == k_entity);
202 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
209 dump_node_vcgattr (ir_node *n)
211 switch (n->op->code) {
218 xfprintf (F, "color: blue");
221 xfprintf (F, "color: lightyellow");
224 xfprintf (F, "color: green");
230 xfprintf (F, "color: yellow");
233 xfprintf (F, DEFAULT_NODE_ATTR);
237 bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
238 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
241 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
242 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
243 if (is_ip_cfop(pred)) {
244 ir_graph *irg = get_ip_cfop_irg(pred);
245 if (pmap_find(irgmap, irg) == NULL) return true;
254 bool is_constlike_node(ir_node *n) {
255 ir_op *op = get_irn_op(n);
256 return (op == op_Const || op == op_Bad || op == op_SymConst);
260 void dump_const_node_local(ir_node *n, pmap *irgmap) {
262 if (!dump_const_local_set()) return;
263 /* Use visited flag to avoid outputting nodes twice.
264 initialize it first. */
265 for (i = 0; i < get_irn_arity(n); i++) {
266 ir_node *con = get_irn_n(n, i);
267 if (is_constlike_node(con)) {
268 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
269 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
272 for (i = 0; i < get_irn_arity(n); i++) {
273 ir_node *con = get_irn_n(n, i);
274 if (is_constlike_node(con) && irn_not_visited(con)) {
275 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
276 mark_irn_visited(con);
277 /* Generate a new name for the node by appending the names of
279 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); PRINT_NODEID(con);
280 fprintf(F, "\" label: \"");
281 dump_node_opcode(con);
282 dump_node_mode (con);
284 dump_node_nodeattr(con);
286 xfprintf (F, " %ld", get_irn_node_nr(con));
289 dump_node_vcgattr(con);
296 dump_node (ir_node *n, pmap * map) {
297 if (dump_const_local_set() && is_constlike_node(n)) return;
300 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
305 dump_node_nodeattr(n);
307 xfprintf (F, " %ld", get_irn_node_nr(n));
310 dump_node_vcgattr(n);
312 dump_const_node_local(n, map);
316 dump_ir_node (ir_node *n)
319 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
321 switch (n->op->code) { /* node label */
323 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
324 xfprintf (F, DEFAULT_NODE_ATTR);
331 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
332 xfprintf (F, DEFAULT_NODE_ATTR);
335 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
336 xfprintf (F, DEFAULT_NODE_ATTR);
339 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
340 if (get_irn_modecode(n) == irm_M)
341 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
343 xfprintf (F, DEFAULT_NODE_ATTR);
346 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
347 xfprintf (F, DEFAULT_NODE_ATTR);
350 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
351 xfprintf (F, DEFAULT_NODE_ATTR);
354 if (n->in[1]->op->code == iro_Cmp) {
355 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
356 get_pnc_string(n->attr.proj));
358 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
360 xfprintf (F, DEFAULT_NODE_ATTR);
363 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.filter.proj);
364 xfprintf (F, DEFAULT_NODE_ATTR);
367 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
368 xfprintf (F, DEFAULT_NODE_ATTR);
371 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(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);
379 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
380 xfprintf (F, DEFAULT_NODE_ATTR);
383 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
384 xfprintf (F, DEFAULT_NODE_ATTR);
387 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
388 xfprintf (F, DEFAULT_NODE_ATTR);
391 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
392 xfprintf (F, DEFAULT_NODE_ATTR);
395 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
396 xfprintf (F, DEFAULT_NODE_ATTR);
399 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
400 xfprintf (F, DEFAULT_NODE_ATTR);
403 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
404 xfprintf (F, DEFAULT_NODE_ATTR);
407 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
408 xfprintf (F, DEFAULT_NODE_ATTR);
411 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
412 xfprintf (F, DEFAULT_NODE_ATTR);
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));
424 xfprintf (F, DEFAULT_NODE_ATTR);
427 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
428 xfprintf (F, DEFAULT_NODE_ATTR);
431 xfprintf (F, "\"%I\"", get_irn_opident(n));
432 xfprintf (F, DEFAULT_NODE_ATTR);
435 xfprintf (F, "\"%I\"", get_irn_opident(n));
436 xfprintf (F, DEFAULT_NODE_ATTR);
439 xfprintf (F, "\"%I\"", get_irn_opident(n));
440 xfprintf (F, DEFAULT_NODE_ATTR);
443 xfprintf (F, "\"%I\"", get_irn_opident(n));
444 xfprintf (F, DEFAULT_NODE_ATTR);
447 xfprintf (F, "\"%I\"", get_irn_opident(n));
448 xfprintf (F, DEFAULT_NODE_ATTR);
451 xfprintf (F, "\"%I\"", get_irn_opident(n));
452 xfprintf (F, DEFAULT_NODE_ATTR);
455 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
456 xfprintf (F, DEFAULT_NODE_ATTR);
460 xfprintf (F, "\"%R\"", n);
461 xfprintf (F, DEFAULT_NODE_ATTR);
464 xfprintf (F, "\"%I\" ", get_irn_opident(n));
465 xfprintf (F, DEFAULT_NODE_ATTR);
468 assert(get_kind(get_Sel_entity(n)) == k_entity);
469 xfprintf (F, "\"%I ", get_irn_opident(n));
470 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
471 xfprintf (F, DEFAULT_NODE_ATTR);
474 assert(get_kind(get_SymConst_type(n)) == k_type);
475 assert(get_type_ident(get_SymConst_type(n)));
476 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
477 switch (n->attr.i.num){
479 xfprintf (F, "tag\" ");
482 xfprintf (F, "size\" ");
488 xfprintf (F, DEFAULT_NODE_ATTR);
491 xfprintf (F, "\"%I\" ", get_irn_opident(n));
492 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
495 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
496 xfprintf (F, DEFAULT_NODE_ATTR);
499 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
500 xfprintf (F, DEFAULT_NODE_ATTR);
503 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
505 xfprintf (F, "}\n"); /* footer */
509 /* dump the edge to the block this node belongs to */
511 dump_ir_block_edge(ir_node *n) {
512 if (dump_const_local_set() && is_constlike_node(n)) return;
513 if (is_no_Block(n)) {
514 xfprintf (F, "edge: { sourcename: \"");
516 xfprintf (F, "\" targetname: \"");
517 PRINT_NODEID(get_nodes_Block(n));
518 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
522 void print_edge_vcgattr(ir_node *from, int to) {
525 if (is_backedge(from, to)) xfprintf (F, BACK_EDGE_ATTR);
527 switch (get_irn_opcode(from)) {
529 xfprintf (F, CF_EDGE_ATTR);
531 case iro_Start: break;
534 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
535 xfprintf (F, CF_EDGE_ATTR);
536 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
537 xfprintf (F, MEM_EDGE_ATTR);
540 case iro_EndReg: break;
541 case iro_EndExcept: break;
543 case iro_Break: break;
544 case iro_Cond: break;
547 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
549 case iro_Const: break;
550 case iro_SymConst:break;
553 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
555 case iro_CallBegin: break;
558 case iro_Minus: break;
564 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
572 case iro_Shrs: break;
575 case iro_Conv: break;
577 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
583 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
586 xfprintf (F, MEM_EDGE_ATTR);
588 case iro_Tuple: break;
591 switch (get_irn_modecode(from)) {
593 xfprintf (F, CF_EDGE_ATTR);
596 xfprintf (F, MEM_EDGE_ATTR);
602 case iro_Unknown: break;
608 /* dump edges to our inputs */
610 dump_ir_data_edges(ir_node *n) {
611 int i, visited = get_irn_visited(n);
613 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
616 for (i = 0; i < get_irn_arity(n); i++) {
617 ir_node * pred = get_irn_n(n, i);
619 if ((interprocedural_view && get_irn_visited(pred) < visited))
620 continue; /* pred not dumped */
621 if (is_backedge(n, i))
622 fprintf (F, "backedge: {sourcename: \"");
624 fprintf (F, "edge: {sourcename: \"");
626 fprintf (F, "\" targetname: \"");
627 if ((dump_const_local_set()) && is_constlike_node(pred))
631 fprintf (F, " label: \"%d\" ", i);
632 print_edge_vcgattr(n, i);
639 dump_out_edge (ir_node *n, void* env) {
641 for (i = 0; i < get_irn_n_outs(n); i++) {
642 assert(get_irn_out(n, i));
643 fprintf (F, "edge: {sourcename: \"");
645 fprintf (F, "\" targetname: \"");
646 PRINT_NODEID(get_irn_out(n, i));
647 fprintf (F, "\" color: red linestyle: dashed");
653 dump_loop_node_edge (ir_loop *loop, int i) {
655 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", loop);
656 PRINT_NODEID(get_loop_node(loop, i));
657 fprintf (F, "\" color: green");
662 void dump_loops (ir_loop *loop) {
664 /* dump this loop node */
665 xfprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
666 loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
667 /* dump edges to nodes in loop -- only if it is a real loop */
668 if (get_loop_depth(loop) != 0) {
669 for (i = 0; i < get_loop_n_nodes(loop); i++) {
670 dump_loop_node_edge(loop, i);
673 for (i = 0; i < get_loop_n_sons(loop); i++) {
674 dump_loops(get_loop_son(loop, i));
679 void dump_loop_info(ir_graph *irg) {
680 ir_graph *rem = current_ir_graph;
681 current_ir_graph = irg;
683 if (get_irg_loop(irg))
684 dump_loops(get_irg_loop(irg));
686 current_ir_graph = rem;
690 /* dumps the edges between nodes and their type or entity attributes. */
691 void dump_node2type_edges (ir_node *n, void *env)
695 switch (get_irn_opcode(n)) {
697 /* @@@ some consts have an entity */
700 if ( (get_SymConst_kind(n) == type_tag)
701 || (get_SymConst_kind(n) == size)) {
702 xfprintf (F, "edge: { sourcename: \"");
704 fprintf (F, "\" targetname: \"%p\" "
705 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
709 xfprintf (F, "edge: { sourcename: \"");
711 fprintf (F, "\" targetname: \"%p\" "
712 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
715 xfprintf (F, "edge: { sourcename: \"");
717 fprintf (F, "\" targetname: \"%p\" "
718 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
721 xfprintf (F, "edge: { sourcename: \"");
723 fprintf (F, "\" targetname: \"%p\" "
724 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
727 xfprintf (F, "edge: { sourcename: \"");
729 fprintf (F, "\" targetname: \"%p\" "
730 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
738 void dump_const_expression(ir_node *value) {
739 ir_graph *rem = current_ir_graph;
740 int rem_dump_const_local = dump_const_local;
741 dump_const_local = 0;
742 current_ir_graph = get_const_code_irg();
743 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
744 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
745 current_ir_graph = rem;
746 dump_const_local = rem_dump_const_local;
750 void print_type_info(type *tp) {
751 if (get_type_state(tp) == layout_undefined) {
752 xfprintf(F, "state: layout_undefined\n");
754 xfprintf(F, "state: layout_fixed,\n");
756 if (get_type_mode(tp))
757 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
758 xfprintf(F, "size: %dB,\n", get_type_size(tp));
762 void print_typespecific_info(type *tp) {
763 switch (get_type_tpop_code(tp)) {
766 if(existent == get_class_peculiarity(tp))
767 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
769 xfprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
773 xfprintf (F, " " TYPE_METH_NODE_ATTR);
784 case tpo_enumeration:
797 void print_type_node(type *tp) {
798 xfprintf (F, "node: {title: \"%p\" ", tp);
799 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
800 xfprintf (F, "info1: \"");
803 print_typespecific_info(tp);
807 /* dumps a type or entity and it's edges. */
809 dump_type_info (type_or_ent *tore, void *env) {
810 int i = 0; /* to shutup gcc */
812 /* dump this type or entity */
814 switch (get_kind(tore)) {
817 entity *ent = (entity *)tore;
820 xfprintf (F, "node: {title: \"%p\" ", tore);
821 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
822 xfprintf (F, "label: ");
823 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
824 switch (get_entity_allocation(ent)) {
825 case dynamic_allocated: fprintf (F, " info1:\"dynamic allocated\n"); break;
826 case automatic_allocated: fprintf (F, " info1:\"automatic allocated\n"); break;
827 case static_allocated: fprintf (F, " info1:\"static allocated\n"); break;
829 switch (get_entity_visibility(ent)) {
830 case local: fprintf (F, "local\n"); break;
831 case external_visible: fprintf (F, "external_visible\n"); break;
832 case external_allocated: fprintf (F, "external_allocate\n"); break;
834 switch (get_entity_variability(ent)) {
835 case uninitialized: fprintf (F, "uninitialized\n");break;
836 case initialized: fprintf (F, "initialized\n"); break;
837 case part_constant: fprintf (F, "part_constant\n");break;
838 case constant: fprintf (F, "constant\n"); break;
840 switch (get_entity_volatility(ent)) {
841 case non_volatile: fprintf (F, "non_volatile\n"); break;
842 case is_volatile: fprintf (F, "is_volatile\n"); break;
844 switch (get_entity_peculiarity(ent)) {
845 case description: fprintf (F, "description\n"); break;
846 case inherited: fprintf (F, "inherited\n"); break;
847 case existent: fprintf (F, "existent\n"); break;
849 if (is_method_type(get_entity_type(ent)))
850 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
851 xfprintf(F, "\"}\n");
853 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
854 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
855 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
856 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
857 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
858 if(is_class_type(get_entity_owner(ent))) {
859 for(i = 0; i < get_entity_n_overwrites(ent); i++)
860 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
861 ENT_OVERWRITES_EDGE_ATTR "}\n",
862 ent, get_entity_overwrites(ent, i));
864 /* attached subgraphs */
865 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
866 if (is_atomic_entity(ent)) {
867 value = get_atomic_ent_value(ent);
868 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
870 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
871 dump_const_expression(value);
873 if (is_compound_entity(ent)) {
874 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
875 value = get_compound_ent_value(ent, i);
876 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
878 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
879 dump_const_expression(value);
880 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
881 ENT_CORR_EDGE_ATTR "}\n", ent,
882 get_compound_ent_value_member(ent, i), i);
889 type *tp = (type *)tore;
891 /* and now the edges */
892 switch (get_type_tpop_code(tp)) {
895 for (i=0; i < get_class_n_supertypes(tp); i++)
896 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
897 TYPE_SUPER_EDGE_ATTR "}\n",
898 tp, get_class_supertype(tp, i));
899 for (i=0; i < get_class_n_members(tp); i++)
900 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
901 TYPE_MEMBER_EDGE_ATTR "}\n",
902 tp, get_class_member(tp, i));
906 for (i=0; i < get_struct_n_members(tp); i++)
907 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
908 TYPE_MEMBER_EDGE_ATTR "}\n",
909 tp, get_struct_member(tp, i));
913 for (i = 0; i < get_method_n_params(tp); i++)
914 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
915 METH_PAR_EDGE_ATTR "}\n",
916 tp, get_method_param_type(tp, i), i);
917 for (i = 0; i < get_method_n_ress(tp); i++)
918 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
919 METH_RES_EDGE_ATTR "}\n",
920 tp, get_method_res_type(tp, i), i);
924 for (i = 0; i < get_union_n_members(tp); i++)
925 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
926 "label: \"\"f" UNION_EDGE_ATTR "}\n",
927 tp, get_union_member(tp, i));
931 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
932 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
933 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
934 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
936 case tpo_enumeration:
941 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
942 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
943 get_pointer_points_to_type(tp), i);
951 break; /* case k_type */
954 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
956 } /* switch kind_or_entity */
959 /************************************************************************/
960 /* open and close vcg file */
961 /************************************************************************/
963 void vcg_open (ir_graph *irg, char *suffix) {
964 char *fname; /* filename to put the vcg information in */
971 /** open file for vcg graph */
972 ent = get_irg_ent(irg);
973 id = ent->ld_name ? ent->ld_name : ent->name;
974 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
975 len = id_to_strlen (id);
977 if (dump_file_suffix)
978 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
980 fname = malloc (len + 5 + strlen(suffix));
981 strncpy (fname, cp, len); /* copy the filename */
983 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
984 strcat (fname, suffix); /* append file suffix */
985 strcat (fname, ".vcg"); /* append the .vcg suffix */
986 F = fopen (fname, "w"); /* open file for writing */
988 panic ("cannot open %s for writing (%m)", fname); /* not reached */
992 strcpy(label, "yes");
994 strcpy (label, "no");
999 "graph: { title: \"ir graph of %s\"\n"
1000 "display_edge_labels: %s\n"
1001 "layoutalgorithm: mindepth\n"
1002 "manhattan_edges: yes\n"
1003 "port_sharing: no\n"
1004 "orientation: bottom_to_top\n"
1005 "classname 1: \"Data\"\n"
1006 "classname 2: \"Block\"\n"
1007 "classname 3: \"Entity type\""
1008 "classname 4: \"Entity owner\""
1009 "classname 5: \"Method Param\""
1010 "classname 6: \"Method Res\""
1011 "classname 7: \"Super\""
1012 "classname 8: \"Union\""
1013 "classname 9: \"Points-to\""
1014 "classname 10: \"Array Element Type\""
1015 "classname 11: \"Overwrites\""
1016 "classname 12: \"Member\""
1019 xfprintf (F, "\n"); /* a separator */
1022 void vcg_open_name (const char *name) {
1023 char *fname; /* filename to put the vcg information in */
1027 /** open file for vcg graph */
1029 fname = malloc (len + 5);
1030 if (dump_file_suffix)
1031 fname = malloc (len + 5 + strlen(dump_file_suffix));
1033 fname = malloc (len + 5);
1034 strcpy (fname, name); /* copy the filename */
1035 if (dump_file_suffix) strcat (fname, dump_file_suffix);
1036 strcat (fname, ".vcg"); /* append the .vcg suffix */
1037 F = fopen (fname, "w"); /* open file for writing */
1039 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1043 strcpy(label, "yes");
1045 strcpy (label, "no");
1050 "graph: { title: \"ir graph of %s\"\n"
1051 "display_edge_labels: %s\n"
1052 "layoutalgorithm: mindepth\n"
1053 "manhattan_edges: yes\n"
1054 "port_sharing: no\n"
1055 "orientation: bottom_to_top\n"
1056 "classname 1: \"Data\"\n"
1057 "classname 2: \"Block\"\n"
1058 "classname 3: \"Entity type\"\n"
1059 "classname 4: \"Entity owner\"\n"
1060 "classname 5: \"Method Param\"\n"
1061 "classname 6: \"Method Res\"\n"
1062 "classname 7: \"Super\"\n"
1063 "classname 8: \"Union\"\n"
1064 "classname 9: \"Points-to\"\n"
1065 "classname 10: \"Array Element Type\"\n"
1066 "classname 11: \"Overwrites\"\n"
1067 "classname 12: \"Member\"\n"
1070 xfprintf (F, "\n"); /* a separator */
1075 xfprintf (F, "}\n"); /* print footer */
1076 fclose (F); /* close vcg file */
1079 /************************************************************************/
1080 /* routines to dump a graph, blocks as conventional nodes. */
1081 /************************************************************************/
1083 int node_floats(ir_node *n) {
1084 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1085 (get_irg_pinned(current_ir_graph) == floats));
1089 dump_whole_node (ir_node *n, void* env) {
1091 if (!node_floats(n)) dump_ir_block_edge(n);
1092 dump_ir_data_edges(n);
1096 dump_ir_graph (ir_graph *irg)
1099 rem = current_ir_graph;
1100 current_ir_graph = irg;
1104 /* walk over the graph */
1105 /* dump_whole_node must be called in post visiting predecessors */
1106 irg_walk(irg->end, NULL, dump_whole_node, NULL);
1108 /* dump the out edges in a separate walk */
1109 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1110 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
1115 current_ir_graph = rem;
1118 /***********************************************************************/
1119 /* the following routines dump the nodes as attached to the blocks. */
1120 /***********************************************************************/
1123 dump_ir_blocks_nodes (ir_node *n, void *env) {
1124 ir_node *block = (ir_node *)env;
1126 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1128 dump_ir_data_edges(n);
1130 if (get_irn_op(n) == op_Bad)
1135 dump_ir_block (ir_node *block, void *env) {
1136 ir_graph *irg = (ir_graph *)env;
1138 if (get_irn_opcode(block) == iro_Block) {
1140 /* This is a block. So dump the vcg information to make a block. */
1141 xfprintf(F, "graph: { title: \"");
1142 PRINT_NODEID(block);
1143 fprintf(F, "\" label: \"");
1144 #ifdef DEBUG_libfirm
1145 xfprintf (F, "%ld", get_irn_node_nr(block));
1147 xfprintf (F, "%I", block->op->name);
1149 if (exc_normal != get_Block_exc (block))
1150 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1152 xfprintf(F, "\" status:clustered color:%s \n",
1153 get_Block_matured (block) ? "yellow" : "red");
1154 /* dump the blocks edges */
1155 dump_ir_data_edges(block);
1157 /* dump the nodes that go into the block */
1158 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1160 /* Close the vcg information for the block */
1161 xfprintf(F, "}\n\n");
1162 dump_const_node_local(block, NULL);
1168 dump_blockless_nodes (ir_node *n, void *env) {
1169 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1171 dump_ir_data_edges(n);
1172 dump_ir_block_edge(n);
1173 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1176 if (node_floats(n)) {
1178 dump_ir_data_edges(n);
1179 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1183 void dump_ir_block_graph_2 (ir_graph *irg)
1186 /* walk over the blocks in the graph */
1187 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1189 /* dump all nodes that are not in a Block */
1190 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1192 /* dump the Bad node */
1194 dump_node(get_irg_bad(irg), NULL);
1198 dump_ir_block_graph (ir_graph *irg)
1201 rem = current_ir_graph;
1202 current_ir_graph = irg;
1206 dump_ir_block_graph_2 (irg);
1208 if (dump_loop_information_flag) dump_loop_info(irg);
1211 current_ir_graph = rem;
1215 /***********************************************************************/
1216 /* the following routines dump a control flow graph */
1217 /***********************************************************************/
1221 dump_block_to_cfg (ir_node *block, void *env) {
1225 if (get_irn_opcode(block) == iro_Block) {
1226 /* This is a block. Dump a node for the block. */
1227 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1228 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1230 if (exc_normal != get_Block_exc (block))
1231 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1233 xfprintf (F, "\" ");
1234 if (dump_dominator_information_flag)
1235 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1236 xfprintf (F, "}\n");
1237 /* Dump the edges */
1238 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1239 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1240 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1241 xfprintf (F, "edge: { sourcename: \"");
1242 PRINT_NODEID(block);
1243 fprintf (F, "\" targetname: \"");
1245 fprintf (F, "\" }\n");
1248 /* Dump dominator edge */
1249 if (dump_dominator_information_flag && get_Block_idom(block)) {
1250 pred = get_Block_idom(block);
1251 xfprintf (F, "edge: { sourcename: \"");
1252 PRINT_NODEID(block);
1253 fprintf (F, "\" targetname: \"");
1255 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1261 dump_cfg (ir_graph *irg)
1263 ir_graph *rem = current_ir_graph;
1264 int ddif = dump_dominator_information_flag;
1265 current_ir_graph = irg;
1266 vcg_open (irg, "-cfg");
1268 if (get_irg_dom_state(irg) != dom_consistent)
1269 dump_dominator_information_flag = 0;
1271 /* walk over the blocks in the graph */
1272 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1273 dump_ir_node (irg->bad);
1275 dump_dominator_information_flag = ddif;
1277 current_ir_graph = rem;
1281 /***********************************************************************/
1282 /* the following routine dumps all type information reachable from an */
1284 /***********************************************************************/
1288 dump_type_graph (ir_graph *irg)
1291 rem = current_ir_graph;
1292 current_ir_graph = irg;
1294 vcg_open (irg, "-type");
1296 /* walk over the blocks in the graph */
1297 type_walk_irg(irg, dump_type_info, NULL, NULL);
1298 /* The walker for the const code can be called several times for the
1299 same (sub) experssion. So that no nodes are dumped several times
1300 we decrease the visited flag of the corresponding graph after each
1301 walk. So now increase it finally. */
1302 inc_irg_visited(get_const_code_irg());
1305 current_ir_graph = rem;
1308 /***********************************************************************/
1309 /* the following routine dumps all type information */
1310 /***********************************************************************/
1314 dump_all_types (void)
1316 vcg_open_name ("All_types");
1317 type_walk(dump_type_info, NULL, NULL);
1318 inc_irg_visited(get_const_code_irg());
1322 /***********************************************************************/
1323 /* dumps a graph with type information */
1324 /***********************************************************************/
1328 dump_ir_graph_w_types (ir_graph *irg)
1331 rem = current_ir_graph;
1332 current_ir_graph = irg;
1334 vcg_open (irg, "-all");
1336 /* dump common ir graph */
1337 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1338 /* dump type info */
1339 type_walk_irg(irg, dump_type_info, NULL, NULL);
1340 inc_irg_visited(get_const_code_irg());
1341 /* dump edges from graph to type info */
1342 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1345 current_ir_graph = rem;
1349 dump_ir_block_graph_w_types (ir_graph *irg)
1352 rem = current_ir_graph;
1353 current_ir_graph = irg;
1355 vcg_open (irg, "-all");
1357 /* dump common blocked ir graph */
1358 dump_ir_block_graph_2(irg);
1359 /* dump type info */
1360 type_walk_irg(irg, dump_type_info, NULL, NULL);
1361 inc_irg_visited(get_const_code_irg());
1362 /* dump edges from graph to type info */
1363 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1366 current_ir_graph = rem;
1369 /***********************************************************************/
1370 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1372 /* dump_ir_block_graph */
1374 /* dump_type_graph */
1375 /* dump_ir_graph_w_types */
1376 /***********************************************************************/
1377 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1379 for (i=0; i < get_irp_n_irgs(); i++) {
1380 dump_graph(get_irp_irg(i));
1385 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1386 abort with a segmentation fault. */
1387 void turn_off_edge_labels() {
1392 void dump_consts_local(bool b) {
1393 dump_const_local = b;
1396 void turn_off_constant_entity_values() {
1400 void dump_keepalive_edges() {
1404 void dump_out_edges() {
1405 dump_out_edge_flag = 1;
1408 void dump_dominator_information() {
1409 dump_dominator_information_flag = 1;
1412 void dump_loop_information() {
1413 dump_loop_information_flag = 1;
1416 void dont_dump_loop_information() {
1417 dump_loop_information_flag = 0;
1420 static void clear_link(ir_node * node, void * env) {
1421 set_irn_link(node, NULL);
1424 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1426 || node_floats(node)
1427 || get_irn_op(node) == op_Bad
1428 || get_irn_op(node) == op_Unknown) {
1429 pmap_entry * entry = pmap_find(map, current_ir_graph);
1431 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1433 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1435 pmap_insert(map, current_ir_graph, arr);
1438 ir_node * block = get_nodes_Block(node);
1439 set_irn_link(node, get_irn_link(block));
1440 set_irn_link(block, node);
1445 static void dump_cg_ir_block(ir_node * block, void * env) {
1447 pmap *irgmap = (pmap *)env;
1448 assert(is_Block(block));
1449 xfprintf(F, "graph: { title: \"");
1450 PRINT_NODEID(block);
1451 fprintf(F, "\" label: \"");
1452 #ifdef DEBUG_libfirm
1453 xfprintf (F, "%ld", get_irn_node_nr(block));
1455 xfprintf (F, "%I", block->op->name);
1457 if (exc_normal != get_Block_exc(block)) {
1458 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1461 xfprintf(F, "\" status:clustered color:%s \n",
1462 get_Block_matured(block) ? "yellow" : "red");
1464 /* dump the blocks edges */
1465 dump_ir_data_edges(block);
1467 /* dump the nodes that go into the block */
1468 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1469 dump_node(node, irgmap);
1470 dump_ir_data_edges(node);
1473 /* Close the vcg information for the block */
1474 xfprintf(F, "}\n\n");
1477 void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1480 xfprintf(F, "graph: { title: \"%p\" label: \"%I\" status:clustered color:white \n",
1481 irg, get_entity_ident(get_irg_ent(irg)));
1483 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1484 ir_node * node = arr[i];
1485 if (is_Block(node)) {
1486 /* Dumps the block and all the nodes in the block , which are to
1487 be found in Block->link. */
1488 dump_cg_ir_block(node, irgmap);
1490 /* Nodes that are not in a Block. */
1491 dump_node(node, NULL);
1492 dump_ir_data_edges(node);
1495 /* Close the vcg information for the irg */
1496 xfprintf(F, "}\n\n");
1499 /* dump interprocedural graph with surrounding methods */
1500 void dump_cg_block_graph(ir_graph * irg) {
1501 pmap * map = pmap_create();
1502 pmap * map2 = pmap_create();
1507 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1508 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1509 pmap_insert(map2, entry->key, entry->value);
1510 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1511 d_cg_block_graph(entry->key, entry->value, map2);
1512 DEL_ARR_F(entry->value);
1518 if (dump_loop_information_flag) dump_loop_info(irg);
1522 static void collect_node(ir_node * node, void *env) {
1524 || node_floats(node)
1525 || get_irn_op(node) == op_Bad
1526 || get_irn_op(node) == op_Unknown) {
1527 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1528 ARR_APP1(ir_node *, arr, node);
1529 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1531 ir_node * block = get_nodes_Block(node);
1532 set_irn_link(node, get_irn_link(block));
1533 set_irn_link(block, node);
1537 /* Links all nodes that have the block field set in the link field of
1538 the block. Adds all blocks and nodes not associated with a block
1539 in a array in irg->link. */
1540 static void collect_nodes() {
1542 for (i = 0; i < get_irp_n_irgs(); i++)
1543 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1544 cg_walk(clear_link, collect_node, NULL);
1547 static void dump_graphs() {
1549 for (i = 0; i < get_irp_n_irgs(); i++) {
1550 current_ir_graph = get_irp_irg(i);
1551 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1555 /* Dump all irgs in interprocedural view to a single file. */
1556 void dump_all_cg_block_graph() {
1558 int rem_view = interprocedural_view;
1559 interprocedural_view = 1;
1560 vcg_open_name ("All_graphs");
1565 if (dump_loop_information_flag)
1566 for (i = 0; i < get_irp_n_irgs(); i++)
1567 dump_loop_info(get_irp_irg(i));
1570 interprocedural_view = rem_view;
1573 /* dump interprocedural block graph with surrounding methods */
1574 void dump_cg_graph(ir_graph * irg) {
1575 pmap * map = pmap_create();
1576 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1580 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1581 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1582 pmap_insert(map2, entry->key, entry->value);
1583 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1584 ir_node ** arr = entry->value;
1586 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1588 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1589 irg_ident, irg_ident);
1591 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1592 ir_node * node = arr[i];
1593 dump_node(node, map2);
1594 dump_ir_data_edges(node);
1595 if (is_Block(node)) {
1596 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1597 dump_node(node, map2);
1598 dump_ir_block_edge(node);
1599 dump_ir_data_edges(node);
1606 /* Close the vcg information for the irg */
1607 xfprintf(F, "}\n\n");