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"
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;
253 void dump_const_node_local(ir_node *n, pmap *irgmap) {
255 if (!dump_const_local_set()) return;
256 /* Use visited flag to avoid outputting nodes twice.
257 initialize it first. */
258 for (i = 0; i < get_irn_arity(n); i++) {
259 ir_node *con = get_irn_n(n, i);
260 if (get_irn_op(con) == op_Const) {
261 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
262 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
265 for (i = 0; i < get_irn_arity(n); i++) {
266 ir_node *con = get_irn_n(n, i);
267 if ((get_irn_op(con) == op_Const) && irn_not_visited(con)) {
268 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
269 mark_irn_visited(con);
270 /* Generate a new name for the node by appending the names of
272 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); PRINT_NODEID(con);
273 fprintf(F, "\" label: \"");
274 dump_node_opcode(con);
275 dump_node_mode (con);
277 dump_node_nodeattr(con);
279 xfprintf (F, " %ld", get_irn_node_nr(con));
282 dump_node_vcgattr(con);
289 dump_node (ir_node *n, pmap * map) {
290 if (dump_const_local_set() && (get_irn_op(n) == op_Const)) return;
293 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
298 dump_node_nodeattr(n);
300 xfprintf (F, " %ld", get_irn_node_nr(n));
303 dump_node_vcgattr(n);
305 dump_const_node_local(n, map);
309 dump_ir_node (ir_node *n)
312 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
314 switch (n->op->code) { /* node label */
316 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
317 xfprintf (F, DEFAULT_NODE_ATTR);
324 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
325 xfprintf (F, DEFAULT_NODE_ATTR);
328 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
329 xfprintf (F, DEFAULT_NODE_ATTR);
332 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
333 if (get_irn_modecode(n) == irm_M)
334 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
336 xfprintf (F, DEFAULT_NODE_ATTR);
339 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, 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 if (n->in[1]->op->code == iro_Cmp) {
348 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
349 get_pnc_string(n->attr.proj));
351 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
353 xfprintf (F, DEFAULT_NODE_ATTR);
356 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.filter.proj);
357 xfprintf (F, DEFAULT_NODE_ATTR);
360 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
361 xfprintf (F, DEFAULT_NODE_ATTR);
364 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
365 xfprintf (F, DEFAULT_NODE_ATTR);
368 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
369 xfprintf (F, DEFAULT_NODE_ATTR);
372 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
373 xfprintf (F, DEFAULT_NODE_ATTR);
376 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
377 xfprintf (F, DEFAULT_NODE_ATTR);
380 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
381 xfprintf (F, DEFAULT_NODE_ATTR);
384 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
385 xfprintf (F, DEFAULT_NODE_ATTR);
388 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
389 xfprintf (F, DEFAULT_NODE_ATTR);
392 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
393 xfprintf (F, DEFAULT_NODE_ATTR);
396 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
397 xfprintf (F, DEFAULT_NODE_ATTR);
400 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
401 xfprintf (F, DEFAULT_NODE_ATTR);
404 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
405 xfprintf (F, DEFAULT_NODE_ATTR);
408 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
409 xfprintf (F, DEFAULT_NODE_ATTR);
412 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
413 xfprintf (F, DEFAULT_NODE_ATTR);
416 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
417 xfprintf (F, DEFAULT_NODE_ATTR);
420 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
421 xfprintf (F, DEFAULT_NODE_ATTR);
424 xfprintf (F, "\"%I\"", get_irn_opident(n));
425 xfprintf (F, DEFAULT_NODE_ATTR);
428 xfprintf (F, "\"%I\"", get_irn_opident(n));
429 xfprintf (F, DEFAULT_NODE_ATTR);
432 xfprintf (F, "\"%I\"", get_irn_opident(n));
433 xfprintf (F, DEFAULT_NODE_ATTR);
436 xfprintf (F, "\"%I\"", get_irn_opident(n));
437 xfprintf (F, DEFAULT_NODE_ATTR);
440 xfprintf (F, "\"%I\"", get_irn_opident(n));
441 xfprintf (F, DEFAULT_NODE_ATTR);
444 xfprintf (F, "\"%I\"", get_irn_opident(n));
445 xfprintf (F, DEFAULT_NODE_ATTR);
448 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
449 xfprintf (F, DEFAULT_NODE_ATTR);
453 xfprintf (F, "\"%R\"", n);
454 xfprintf (F, DEFAULT_NODE_ATTR);
457 xfprintf (F, "\"%I\" ", get_irn_opident(n));
458 xfprintf (F, DEFAULT_NODE_ATTR);
461 assert(get_kind(get_Sel_entity(n)) == k_entity);
462 xfprintf (F, "\"%I ", get_irn_opident(n));
463 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
464 xfprintf (F, DEFAULT_NODE_ATTR);
467 assert(get_kind(get_SymConst_type(n)) == k_type);
468 assert(get_type_ident(get_SymConst_type(n)));
469 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
470 switch (n->attr.i.num){
472 xfprintf (F, "tag\" ");
475 xfprintf (F, "size\" ");
481 xfprintf (F, DEFAULT_NODE_ATTR);
484 xfprintf (F, "\"%I\" ", get_irn_opident(n));
485 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
488 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
489 xfprintf (F, DEFAULT_NODE_ATTR);
492 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
493 xfprintf (F, DEFAULT_NODE_ATTR);
496 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
498 xfprintf (F, "}\n"); /* footer */
502 /* dump the edge to the block this node belongs to */
504 dump_ir_block_edge(ir_node *n) {
505 if (dump_const_local_set() && (get_irn_op(n) == op_Const)) return;
506 if (is_no_Block(n)) {
507 xfprintf (F, "edge: { sourcename: \"");
509 xfprintf (F, "\" targetname: \"");
510 PRINT_NODEID(get_nodes_Block(n));
511 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
515 void print_edge_vcgattr(ir_node *from, int to) {
518 if (is_backedge(from, to)) xfprintf (F, BACK_EDGE_ATTR);
520 switch (get_irn_opcode(from)) {
522 xfprintf (F, CF_EDGE_ATTR);
524 case iro_Start: break;
527 if (get_irn_mode(get_End_keepalive(from, to)) == mode_R)
528 xfprintf (F, CF_EDGE_ATTR);
529 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
530 xfprintf (F, MEM_EDGE_ATTR);
533 case iro_EndReg: break;
534 case iro_EndExcept: break;
536 case iro_Break: break;
537 case iro_Cond: break;
540 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
542 case iro_Const: break;
543 case iro_SymConst:break;
546 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
548 case iro_CallBegin: break;
551 case iro_Minus: break;
557 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
565 case iro_Shrs: break;
568 case iro_Conv: break;
570 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
576 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
579 xfprintf (F, MEM_EDGE_ATTR);
581 case iro_Tuple: break;
584 switch (get_irn_modecode(from)) {
586 xfprintf (F, CF_EDGE_ATTR);
589 xfprintf (F, MEM_EDGE_ATTR);
595 case iro_Unknown: break;
601 /* dump edges to our inputs */
603 dump_ir_data_edges(ir_node *n) {
604 int i, visited = get_irn_visited(n);
606 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
609 for (i = 0; i < get_irn_arity(n); i++) {
610 ir_node * pred = get_irn_n(n, i);
612 if ((interprocedural_view && get_irn_visited(pred) < visited))
613 continue; /* pred not dumped */
614 if (is_backedge(n, i))
615 fprintf (F, "backedge: {sourcename: \"");
617 fprintf (F, "edge: {sourcename: \"");
619 fprintf (F, "\" targetname: \"");
620 if ((dump_const_local_set()) && (get_irn_op(pred) == op_Const))
624 fprintf (F, " label: \"%d\" ", i);
625 print_edge_vcgattr(n, i);
632 dump_out_edge (ir_node *n, void* env) {
634 for (i = 0; i < get_irn_n_outs(n); i++) {
635 assert(get_irn_out(n, i));
636 fprintf (F, "edge: {sourcename: \"");
638 fprintf (F, "\" targetname: \"");
639 PRINT_NODEID(get_irn_out(n, i));
640 fprintf (F, "\" color: red linestyle: dashed");
646 dump_loop_node_edge (ir_loop *loop, int i) {
648 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", loop);
649 PRINT_NODEID(get_loop_node(loop, i));
650 fprintf (F, "\" color: green");
655 void dump_loops (ir_loop *loop) {
657 /* dump this loop node */
658 xfprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
659 loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
660 /* dump edges to nodes in loop -- only if it is a real loop */
661 if (get_loop_depth(loop) != 0) {
662 for (i = 0; i < get_loop_n_nodes(loop); i++) {
663 dump_loop_node_edge(loop, i);
666 for (i = 0; i < get_loop_n_sons(loop); i++) {
667 dump_loops(get_loop_son(loop, i));
672 void dump_loop_info(ir_graph *irg) {
673 ir_graph *rem = current_ir_graph;
674 current_ir_graph = irg;
676 if (get_irg_loop(irg))
677 dump_loops(get_irg_loop(irg));
679 current_ir_graph = rem;
683 /* dumps the edges between nodes and their type or entity attributes. */
684 void dump_node2type_edges (ir_node *n, void *env)
688 switch (get_irn_opcode(n)) {
690 /* @@@ some consts have an entity */
693 if ( (get_SymConst_kind(n) == type_tag)
694 || (get_SymConst_kind(n) == size)) {
695 xfprintf (F, "edge: { sourcename: \"");
697 fprintf (F, "\" targetname: \"%p\" "
698 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
702 xfprintf (F, "edge: { sourcename: \"");
704 fprintf (F, "\" targetname: \"%p\" "
705 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
708 xfprintf (F, "edge: { sourcename: \"");
710 fprintf (F, "\" targetname: \"%p\" "
711 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
714 xfprintf (F, "edge: { sourcename: \"");
716 fprintf (F, "\" targetname: \"%p\" "
717 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
720 xfprintf (F, "edge: { sourcename: \"");
722 fprintf (F, "\" targetname: \"%p\" "
723 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
731 void dump_const_expression(ir_node *value) {
732 ir_graph *rem = current_ir_graph;
733 current_ir_graph = get_const_code_irg();
734 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
735 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
736 current_ir_graph = rem;
740 void print_type_info(type *tp) {
741 if (get_type_state(tp) == layout_undefined) {
742 xfprintf(F, "state: layout_undefined\n");
744 xfprintf(F, "state: layout_fixed,\n");
746 if (get_type_mode(tp))
747 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
748 xfprintf(F, "size: %dB,\n", get_type_size(tp));
752 void print_typespecific_info(type *tp) {
753 switch (get_type_tpop_code(tp)) {
756 if(existent == get_class_peculiarity(tp))
757 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
759 xfprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
763 xfprintf (F, " " TYPE_METH_NODE_ATTR);
774 case tpo_enumeration:
787 void print_type_node(type *tp) {
788 xfprintf (F, "node: {title: \"%p\" ", tp);
789 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
790 xfprintf (F, "info1: \"");
793 print_typespecific_info(tp);
797 /* dumps a type or entity and it's edges. */
799 dump_type_info (type_or_ent *tore, void *env) {
800 int i = 0; /* to shutup gcc */
802 /* dump this type or entity */
804 switch (get_kind(tore)) {
807 entity *ent = (entity *)tore;
810 xfprintf (F, "node: {title: \"%p\" ", tore);
811 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
812 xfprintf (F, "label: ");
813 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
814 switch (get_entity_allocation(ent)) {
815 case dynamic_allocated: fprintf (F, " info1:\"dynamic allocated\n"); break;
816 case automatic_allocated: fprintf (F, " info1:\"automatic allocated\n"); break;
817 case static_allocated: fprintf (F, " info1:\"static allocated\n"); break;
819 switch (get_entity_visibility(ent)) {
820 case local: fprintf (F, "local\n"); break;
821 case external_visible: fprintf (F, "external_visible\n"); break;
822 case external_allocated: fprintf (F, "external_allocate\n"); break;
824 switch (get_entity_variability(ent)) {
825 case uninitialized: fprintf (F, "uninitialized\n");break;
826 case initialized: fprintf (F, "initialized\n"); break;
827 case part_constant: fprintf (F, "part_constant\n");break;
828 case constant: fprintf (F, "constant\n"); break;
830 switch (get_entity_volatility(ent)) {
831 case non_volatile: fprintf (F, "non_volatile\n"); break;
832 case is_volatile: fprintf (F, "is_volatile\n"); break;
834 switch (get_entity_peculiarity(ent)) {
835 case description: fprintf (F, "description\n"); break;
836 case inherited: fprintf (F, "inherited\n"); break;
837 case existent: fprintf (F, "existent\n"); break;
839 if (is_method_type(get_entity_type(ent)))
840 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
841 xfprintf(F, "\"}\n");
843 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
844 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
845 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
846 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
847 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
848 if(is_class_type(get_entity_owner(ent))) {
849 for(i = 0; i < get_entity_n_overwrites(ent); i++)
850 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
851 ENT_OVERWRITES_EDGE_ATTR "}\n",
852 ent, get_entity_overwrites(ent, i));
854 /* attached subgraphs */
855 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
856 if (is_atomic_entity(ent)) {
857 value = get_atomic_ent_value(ent);
858 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
860 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
861 dump_const_expression(value);
863 if (is_compound_entity(ent)) {
864 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
865 value = get_compound_ent_value(ent, i);
866 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
868 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
869 dump_const_expression(value);
870 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
871 ENT_CORR_EDGE_ATTR "}\n", ent,
872 get_compound_ent_value_member(ent, i), i);
879 type *tp = (type *)tore;
881 /* and now the edges */
882 switch (get_type_tpop_code(tp)) {
885 for (i=0; i < get_class_n_supertypes(tp); i++)
886 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
887 TYPE_SUPER_EDGE_ATTR "}\n",
888 tp, get_class_supertype(tp, i));
889 for (i=0; i < get_class_n_members(tp); i++)
890 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
891 TYPE_MEMBER_EDGE_ATTR "}\n",
892 tp, get_class_member(tp, i));
896 for (i=0; i < get_struct_n_members(tp); i++)
897 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
898 TYPE_MEMBER_EDGE_ATTR "}\n",
899 tp, get_struct_member(tp, i));
903 for (i = 0; i < get_method_n_params(tp); i++)
904 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
905 METH_PAR_EDGE_ATTR "}\n",
906 tp, get_method_param_type(tp, i), i);
907 for (i = 0; i < get_method_n_ress(tp); i++)
908 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
909 METH_RES_EDGE_ATTR "}\n",
910 tp, get_method_res_type(tp, i), i);
914 for (i = 0; i < get_union_n_members(tp); i++)
915 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
916 "label: \"\"f" UNION_EDGE_ATTR "}\n",
917 tp, get_union_member(tp, i));
921 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
922 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
923 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
924 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
926 case tpo_enumeration:
931 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
932 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
933 get_pointer_points_to_type(tp), i);
941 break; /* case k_type */
944 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
946 } /* switch kind_or_entity */
949 /************************************************************************/
950 /* open and close vcg file */
951 /************************************************************************/
953 void vcg_open (ir_graph *irg, char *suffix) {
954 char *fname; /* filename to put the vcg information in */
961 /** open file for vcg graph */
962 ent = get_irg_ent(irg);
963 id = ent->ld_name ? ent->ld_name : ent->name;
964 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
965 len = id_to_strlen (id);
967 if (dump_file_suffix)
968 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
970 fname = malloc (len + 5 + strlen(suffix));
971 strncpy (fname, cp, len); /* copy the filename */
973 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
974 strcat (fname, suffix); /* append file suffix */
975 strcat (fname, ".vcg"); /* append the .vcg suffix */
976 F = fopen (fname, "w"); /* open file for writing */
978 panic ("cannot open %s for writing (%m)", fname); /* not reached */
982 strcpy(label, "yes");
984 strcpy (label, "no");
989 "graph: { title: \"ir graph of %s\"\n"
990 "display_edge_labels: %s\n"
991 "layoutalgorithm: mindepth\n"
992 "manhattan_edges: yes\n"
994 "orientation: bottom_to_top\n"
995 "classname 1: \"Data\"\n"
996 "classname 2: \"Block\"\n"
997 "classname 3: \"Entity type\""
998 "classname 4: \"Entity owner\""
999 "classname 5: \"Method Param\""
1000 "classname 6: \"Method Res\""
1001 "classname 7: \"Super\""
1002 "classname 8: \"Union\""
1003 "classname 9: \"Points-to\""
1004 "classname 10: \"Array Element Type\""
1005 "classname 11: \"Overwrites\""
1006 "classname 12: \"Member\""
1009 xfprintf (F, "\n"); /* a separator */
1012 void vcg_open_name (const char *name) {
1013 char *fname; /* filename to put the vcg information in */
1017 /** open file for vcg graph */
1019 fname = malloc (len + 5);
1020 if (dump_file_suffix)
1021 fname = malloc (len + 5 + strlen(dump_file_suffix));
1023 fname = malloc (len + 5);
1024 strcpy (fname, name); /* copy the filename */
1025 if (dump_file_suffix) strcat (fname, dump_file_suffix);
1026 strcat (fname, ".vcg"); /* append the .vcg suffix */
1027 F = fopen (fname, "w"); /* open file for writing */
1029 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1033 strcpy(label, "yes");
1035 strcpy (label, "no");
1040 "graph: { title: \"ir graph of %s\"\n"
1041 "display_edge_labels: %s\n"
1042 "layoutalgorithm: mindepth\n"
1043 "manhattan_edges: yes\n"
1044 "port_sharing: no\n"
1045 "orientation: bottom_to_top\n"
1046 "classname 1: \"Data\"\n"
1047 "classname 2: \"Block\"\n"
1048 "classname 3: \"Entity type\"\n"
1049 "classname 4: \"Entity owner\"\n"
1050 "classname 5: \"Method Param\"\n"
1051 "classname 6: \"Method Res\"\n"
1052 "classname 7: \"Super\"\n"
1053 "classname 8: \"Union\"\n"
1054 "classname 9: \"Points-to\"\n"
1055 "classname 10: \"Array Element Type\"\n"
1056 "classname 11: \"Overwrites\"\n"
1057 "classname 12: \"Member\"\n"
1060 xfprintf (F, "\n"); /* a separator */
1065 xfprintf (F, "}\n"); /* print footer */
1066 fclose (F); /* close vcg file */
1069 /************************************************************************/
1070 /* routines to dump a graph, blocks as conventional nodes. */
1071 /************************************************************************/
1073 int node_floats(ir_node *n) {
1074 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1075 (get_irg_pinned(current_ir_graph) == floats));
1079 dump_whole_node (ir_node *n, void* env) {
1081 if (!node_floats(n)) dump_ir_block_edge(n);
1082 dump_ir_data_edges(n);
1086 dump_ir_graph (ir_graph *irg)
1089 rem = current_ir_graph;
1090 current_ir_graph = irg;
1094 /* walk over the graph */
1095 /* dump_whole_node must be called in post visiting predecessors */
1096 irg_walk(irg->end, NULL, dump_whole_node, NULL);
1098 /* dump the out edges in a separate walk */
1099 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1100 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
1105 current_ir_graph = rem;
1108 /***********************************************************************/
1109 /* the following routines dump the nodes as attached to the blocks. */
1110 /***********************************************************************/
1113 dump_ir_blocks_nodes (ir_node *n, void *env) {
1114 ir_node *block = (ir_node *)env;
1116 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1118 dump_ir_data_edges(n);
1120 if (get_irn_op(n) == op_Bad)
1125 dump_ir_block (ir_node *block, void *env) {
1126 ir_graph *irg = (ir_graph *)env;
1128 if (get_irn_opcode(block) == iro_Block) {
1130 /* This is a block. So dump the vcg information to make a block. */
1131 xfprintf(F, "graph: { title: \"");
1132 PRINT_NODEID(block);
1133 fprintf(F, "\" label: \"");
1134 #ifdef DEBUG_libfirm
1135 xfprintf (F, "%ld", get_irn_node_nr(block));
1137 xfprintf (F, "%I", block->op->name);
1139 if (exc_normal != get_Block_exc (block))
1140 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1142 xfprintf(F, "\" status:clustered color:%s \n",
1143 get_Block_matured (block) ? "yellow" : "red");
1144 /* dump the blocks edges */
1145 dump_ir_data_edges(block);
1147 /* dump the nodes that go into the block */
1148 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1150 /* Close the vcg information for the block */
1151 xfprintf(F, "}\n\n");
1157 dump_blockless_nodes (ir_node *n, void *env) {
1158 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1160 dump_ir_data_edges(n);
1161 dump_ir_block_edge(n);
1162 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1165 if (node_floats(n)) {
1167 dump_ir_data_edges(n);
1168 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1172 void dump_ir_block_graph_2 (ir_graph *irg)
1175 /* walk over the blocks in the graph */
1176 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1178 /* dump all nodes that are not in a Block */
1179 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1181 /* dump the Bad node */
1183 dump_node(get_irg_bad(irg), NULL);
1187 dump_ir_block_graph (ir_graph *irg)
1190 rem = current_ir_graph;
1191 current_ir_graph = irg;
1195 dump_ir_block_graph_2 (irg);
1197 if (dump_loop_information_flag) {
1198 dump_loop_info(irg);
1202 current_ir_graph = rem;
1206 /***********************************************************************/
1207 /* the following routines dump a control flow graph */
1208 /***********************************************************************/
1212 dump_block_to_cfg (ir_node *block, void *env) {
1216 if (get_irn_opcode(block) == iro_Block) {
1217 /* This is a block. Dump a node for the block. */
1218 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1219 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1221 if (exc_normal != get_Block_exc (block))
1222 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1224 xfprintf (F, "\" ");
1225 if (dump_dominator_information_flag)
1226 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1227 xfprintf (F, "}\n");
1228 /* Dump the edges */
1229 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1230 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1231 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1232 xfprintf (F, "edge: { sourcename: \"");
1233 PRINT_NODEID(block);
1234 fprintf (F, "\" targetname: \"");
1236 fprintf (F, "\" }\n");
1239 /* Dump dominator edge */
1240 if (dump_dominator_information_flag && get_Block_idom(block)) {
1241 pred = get_Block_idom(block);
1242 xfprintf (F, "edge: { sourcename: \"");
1243 PRINT_NODEID(block);
1244 fprintf (F, "\" targetname: \"");
1246 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1252 dump_cfg (ir_graph *irg)
1254 ir_graph *rem = current_ir_graph;
1255 int ddif = dump_dominator_information_flag;
1256 current_ir_graph = irg;
1257 vcg_open (irg, "-cfg");
1259 if (get_irg_dom_state(irg) != dom_consistent)
1260 dump_dominator_information_flag = 0;
1262 /* walk over the blocks in the graph */
1263 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1264 dump_ir_node (irg->bad);
1266 dump_dominator_information_flag = ddif;
1268 current_ir_graph = rem;
1272 /***********************************************************************/
1273 /* the following routine dumps all type information reachable from an */
1275 /***********************************************************************/
1279 dump_type_graph (ir_graph *irg)
1282 rem = current_ir_graph;
1283 current_ir_graph = irg;
1285 vcg_open (irg, "-type");
1287 /* walk over the blocks in the graph */
1288 type_walk_irg(irg, dump_type_info, NULL, NULL);
1289 /* The walker for the const code can be called several times for the
1290 same (sub) experssion. So that no nodes are dumped several times
1291 we decrease the visited flag of the corresponding graph after each
1292 walk. So now increase it finally. */
1293 inc_irg_visited(get_const_code_irg());
1296 current_ir_graph = rem;
1299 /***********************************************************************/
1300 /* the following routine dumps all type information */
1301 /***********************************************************************/
1305 dump_all_types (void)
1307 vcg_open_name ("All_types");
1308 type_walk(dump_type_info, NULL, NULL);
1309 inc_irg_visited(get_const_code_irg());
1313 /***********************************************************************/
1314 /* dumps a graph with type information */
1315 /***********************************************************************/
1319 dump_ir_graph_w_types (ir_graph *irg)
1322 rem = current_ir_graph;
1323 current_ir_graph = irg;
1325 vcg_open (irg, "-all");
1327 /* dump common ir graph */
1328 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1329 /* dump type info */
1330 type_walk_irg(irg, dump_type_info, NULL, NULL);
1331 inc_irg_visited(get_const_code_irg());
1332 /* dump edges from graph to type info */
1333 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1336 current_ir_graph = rem;
1340 dump_ir_block_graph_w_types (ir_graph *irg)
1343 rem = current_ir_graph;
1344 current_ir_graph = irg;
1346 vcg_open (irg, "-all");
1348 /* dump common blocked ir graph */
1349 dump_ir_block_graph_2(irg);
1350 /* dump type info */
1351 type_walk_irg(irg, dump_type_info, NULL, NULL);
1352 inc_irg_visited(get_const_code_irg());
1353 /* dump edges from graph to type info */
1354 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1357 current_ir_graph = rem;
1360 /***********************************************************************/
1361 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1363 /* dump_ir_block_graph */
1365 /* dump_type_graph */
1366 /* dump_ir_graph_w_types */
1367 /***********************************************************************/
1368 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1370 for (i=0; i < get_irp_n_irgs(); i++) {
1371 dump_graph(get_irp_irg(i));
1376 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1377 abort with a segmentation fault. */
1378 void turn_off_edge_labels() {
1383 void dump_consts_local(bool b) {
1384 dump_const_local = b;
1387 void turn_off_constant_entity_values() {
1391 void dump_keepalive_edges() {
1395 void dump_out_edges() {
1396 dump_out_edge_flag = 1;
1399 void dump_dominator_information() {
1400 dump_dominator_information_flag = 1;
1403 void dump_loop_information() {
1404 dump_loop_information_flag = 1;
1407 void dont_dump_loop_information() {
1408 dump_loop_information_flag = 0;
1411 static void clear_link(ir_node * node, void * env) {
1412 set_irn_link(node, NULL);
1415 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1417 || node_floats(node)
1418 || get_irn_op(node) == op_Bad
1419 || get_irn_op(node) == op_Unknown) {
1420 pmap_entry * entry = pmap_find(map, current_ir_graph);
1422 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1424 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1426 pmap_insert(map, current_ir_graph, arr);
1429 ir_node * block = get_nodes_Block(node);
1430 set_irn_link(node, get_irn_link(block));
1431 set_irn_link(block, node);
1436 static void dump_cg_ir_block(ir_node * block, void * env) {
1438 pmap *irgmap = (pmap *)env;
1439 assert(is_Block(block));
1440 xfprintf(F, "graph: { title: \"");
1441 PRINT_NODEID(block);
1442 fprintf(F, "\" label: \"");
1443 #ifdef DEBUG_libfirm
1444 xfprintf (F, "%ld", get_irn_node_nr(block));
1446 xfprintf (F, "%I", block->op->name);
1448 if (exc_normal != get_Block_exc(block)) {
1449 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1452 xfprintf(F, "\" status:clustered color:%s \n",
1453 get_Block_matured(block) ? "yellow" : "red");
1455 /* dump the blocks edges */
1456 dump_ir_data_edges(block);
1458 /* dump the nodes that go into the block */
1459 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1460 dump_node(node, irgmap);
1461 dump_ir_data_edges(node);
1464 /* Close the vcg information for the block */
1465 xfprintf(F, "}\n\n");
1468 void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1471 xfprintf(F, "graph: { title: \"%p\" label: \"%I\" status:clustered color:white \n",
1472 irg, get_entity_ident(get_irg_ent(irg)));
1474 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1475 ir_node * node = arr[i];
1476 if (is_Block(node)) {
1477 /* Dumps the block and all the nodes in the block , which are to
1478 be found in Block->link. */
1479 dump_cg_ir_block(node, irgmap);
1481 /* Nodes that are not in a Block. */
1482 dump_node(node, NULL);
1483 dump_ir_data_edges(node);
1486 /* Close the vcg information for the irg */
1487 xfprintf(F, "}\n\n");
1490 /* dump interprocedural graph with surrounding methods */
1491 void dump_cg_block_graph(ir_graph * irg) {
1492 pmap * map = pmap_create();
1493 pmap * map2 = pmap_create();
1498 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1499 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1500 pmap_insert(map2, entry->key, entry->value);
1501 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1502 d_cg_block_graph(entry->key, entry->value, map2);
1503 DEL_ARR_F(entry->value);
1509 if (dump_loop_information_flag) dump_loop_info(irg);
1513 static void collect_node(ir_node * node, void *env) {
1515 || node_floats(node)
1516 || get_irn_op(node) == op_Bad
1517 || get_irn_op(node) == op_Unknown) {
1518 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1519 ARR_APP1(ir_node *, arr, node);
1520 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1522 ir_node * block = get_nodes_Block(node);
1523 set_irn_link(node, get_irn_link(block));
1524 set_irn_link(block, node);
1528 /* Links all nodes that have the block field set in the link field of
1529 the block. Adds all blocks and nodes not associated with a block
1530 in a array in irg->link. */
1531 static void collect_nodes() {
1533 for (i = 0; i < get_irp_n_irgs(); i++)
1534 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1535 cg_walk(clear_link, collect_node, NULL);
1538 static void dump_graphs() {
1540 for (i = 0; i < get_irp_n_irgs(); i++) {
1541 current_ir_graph = get_irp_irg(i);
1542 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1546 /* Dump all irgs in interprocedural view to a single file. */
1547 void dump_all_cg_block_graph() {
1549 int rem_view = interprocedural_view;
1550 interprocedural_view = 1;
1551 vcg_open_name ("All_graphs");
1556 if (dump_loop_information_flag)
1557 for (i = 0; i < get_irp_n_irgs(); i++)
1558 dump_loop_info(get_irp_irg(i));
1561 interprocedural_view = rem_view;
1564 /* dump interprocedural block graph with surrounding methods */
1565 void dump_cg_graph(ir_graph * irg) {
1566 pmap * map = pmap_create();
1567 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1571 irg_walk_graph(irg, clear_link, (irg_walk_func) collect_blocks_floats_cg, map);
1572 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1573 pmap_insert(map2, entry->key, entry->value);
1574 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1575 ir_node ** arr = entry->value;
1577 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1579 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1580 irg_ident, irg_ident);
1582 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1583 ir_node * node = arr[i];
1584 dump_node(node, map2);
1585 dump_ir_data_edges(node);
1586 if (is_Block(node)) {
1587 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1588 dump_node(node, map2);
1589 dump_ir_block_edge(node);
1590 dump_ir_data_edges(node);
1597 /* Close the vcg information for the irg */
1598 xfprintf(F, "}\n\n");