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: red"
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. */
104 static int Bad_dumped;
106 static void dump_ir_blocks_nodes (ir_node *n, void *env);
107 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 void dump_entity_node(entity *ent) {
808 xfprintf (F, "node: {title: \"%p\" ", ent);
809 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
810 xfprintf (F, "label: ");
811 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
812 switch (get_entity_allocation(ent)) {
813 case dynamic_allocated: fprintf (F, " info1:\"dynamic allocated\n"); break;
814 case automatic_allocated: fprintf (F, " info1:\"automatic allocated\n"); break;
815 case static_allocated: fprintf (F, " info1:\"static allocated\n"); break;
817 switch (get_entity_visibility(ent)) {
818 case local: fprintf (F, "local\n"); break;
819 case external_visible: fprintf (F, "external_visible\n"); break;
820 case external_allocated: fprintf (F, "external_allocate\n"); break;
822 switch (get_entity_variability(ent)) {
823 case uninitialized: fprintf (F, "uninitialized\n");break;
824 case initialized: fprintf (F, "initialized\n"); break;
825 case part_constant: fprintf (F, "part_constant\n");break;
826 case constant: fprintf (F, "constant\n"); break;
828 switch (get_entity_volatility(ent)) {
829 case non_volatile: fprintf (F, "non_volatile\n"); break;
830 case is_volatile: fprintf (F, "is_volatile\n"); break;
832 switch (get_entity_peculiarity(ent)) {
833 case description: fprintf (F, "description\n"); break;
834 case inherited: fprintf (F, "inherited\n"); break;
835 case existent: fprintf (F, "existent\n"); break;
837 if (is_method_type(get_entity_type(ent)))
838 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
839 xfprintf(F, "\"}\n");
842 /* dumps a type or entity and it's edges. */
844 dump_type_info (type_or_ent *tore, void *env) {
845 int i = 0; /* to shutup gcc */
847 /* dump this type or entity */
849 switch (get_kind(tore)) {
852 entity *ent = (entity *)tore;
855 dump_entity_node(ent);
857 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
858 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
859 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
860 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
861 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
862 if(is_class_type(get_entity_owner(ent))) {
863 for(i = 0; i < get_entity_n_overwrites(ent); i++)
864 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
865 ENT_OVERWRITES_EDGE_ATTR "}\n",
866 ent, get_entity_overwrites(ent, i));
868 /* attached subgraphs */
869 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
870 if (is_atomic_entity(ent)) {
871 value = get_atomic_ent_value(ent);
872 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
874 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
875 dump_const_expression(value);
877 if (is_compound_entity(ent)) {
878 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
879 value = get_compound_ent_value(ent, i);
880 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
882 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
883 dump_const_expression(value);
884 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
885 ENT_CORR_EDGE_ATTR "}\n", ent,
886 get_compound_ent_value_member(ent, i), i);
893 type *tp = (type *)tore;
895 /* and now the edges */
896 switch (get_type_tpop_code(tp)) {
899 for (i=0; i < get_class_n_supertypes(tp); i++)
900 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
901 TYPE_SUPER_EDGE_ATTR "}\n",
902 tp, get_class_supertype(tp, i));
903 for (i=0; i < get_class_n_members(tp); i++)
904 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
905 TYPE_MEMBER_EDGE_ATTR "}\n",
906 tp, get_class_member(tp, i));
910 for (i=0; i < get_struct_n_members(tp); i++)
911 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
912 TYPE_MEMBER_EDGE_ATTR "}\n",
913 tp, get_struct_member(tp, i));
917 for (i = 0; i < get_method_n_params(tp); i++)
918 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
919 METH_PAR_EDGE_ATTR "}\n",
920 tp, get_method_param_type(tp, i), i);
921 for (i = 0; i < get_method_n_ress(tp); i++)
922 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
923 METH_RES_EDGE_ATTR "}\n",
924 tp, get_method_res_type(tp, i), i);
928 for (i = 0; i < get_union_n_members(tp); i++)
929 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
930 "label: \"\"f" UNION_EDGE_ATTR "}\n",
931 tp, get_union_member(tp, i));
935 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
936 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
937 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
938 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
940 case tpo_enumeration:
945 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
946 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
947 get_pointer_points_to_type(tp), i);
955 break; /* case k_type */
958 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
960 } /* switch kind_or_entity */
963 /* dumps a class type node and a superclass edge.
964 If env != null dumps entities of classes and overwrites edges. */
966 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
967 int i = 0; /* to shutup gcc */
969 /* dump this type or entity */
970 switch (get_kind(tore)) {
972 entity *ent = (entity *)tore;
973 if ((env) && is_class_type(get_entity_owner(ent))) {
975 dump_entity_node(ent);
977 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
978 TYPE_MEMBER_EDGE_ATTR "}\n", get_entity_owner(ent), ent);
979 for(i = 0; i < get_entity_n_overwrites(ent); i++)
980 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
981 ENT_OVERWRITES_EDGE_ATTR "}\n",
982 ent, get_entity_overwrites(ent, i));
984 } break; /* case k_entity */
987 type *tp = (type *)tore;
988 switch (get_type_tpop_code(tp)) {
991 /* and now the edges */
992 for (i=0; i < get_class_n_supertypes(tp); i++)
993 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
994 TYPE_SUPER_EDGE_ATTR "}\n",
995 tp, get_class_supertype(tp, i));
1000 break; /* case k_type */
1003 printf(" *** irdump, %s(l.%i), faulty type.\n", __FUNCTION__, __LINE__);
1005 } /* switch kind_or_entity */
1008 /************************************************************************/
1009 /* open and close vcg file */
1010 /************************************************************************/
1012 static void vcg_open (ir_graph *irg, char *suffix) {
1013 char *fname; /* filename to put the vcg information in */
1020 /** open file for vcg graph */
1021 ent = get_irg_ent(irg);
1022 id = ent->ld_name ? ent->ld_name : ent->name;
1023 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
1024 len = id_to_strlen (id);
1025 cp = id_to_str (id);
1026 if (dump_file_suffix)
1027 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
1029 fname = malloc (len + 5 + strlen(suffix));
1030 strncpy (fname, cp, len); /* copy the filename */
1032 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
1033 strcat (fname, suffix); /* append file suffix */
1034 strcat (fname, ".vcg"); /* append the .vcg suffix */
1035 F = fopen (fname, "w"); /* open file for writing */
1037 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1041 strcpy(label, "yes");
1043 strcpy (label, "no");
1048 "graph: { title: \"ir graph of %s\"\n"
1049 "display_edge_labels: %s\n"
1050 "layoutalgorithm: mindepth\n"
1051 "manhattan_edges: yes\n"
1052 "port_sharing: no\n"
1053 "orientation: bottom_to_top\n"
1054 "classname 1: \"Data\"\n"
1055 "classname 2: \"Block\"\n"
1056 "classname 3: \"Entity type\""
1057 "classname 4: \"Entity owner\""
1058 "classname 5: \"Method Param\""
1059 "classname 6: \"Method Res\""
1060 "classname 7: \"Super\""
1061 "classname 8: \"Union\""
1062 "classname 9: \"Points-to\""
1063 "classname 10: \"Array Element Type\""
1064 "classname 11: \"Overwrites\""
1065 "classname 12: \"Member\""
1068 xfprintf (F, "\n"); /* a separator */
1071 static void vcg_open_name (const char *name) {
1072 char *fname; /* filename to put the vcg information in */
1076 /** open file for vcg graph */
1078 fname = malloc (len + 5);
1079 if (dump_file_suffix)
1080 fname = malloc (len + 5 + strlen(dump_file_suffix));
1082 fname = malloc (len + 5);
1083 strcpy (fname, name); /* copy the filename */
1084 if (dump_file_suffix) strcat (fname, dump_file_suffix);
1085 strcat (fname, ".vcg"); /* append the .vcg suffix */
1086 F = fopen (fname, "w"); /* open file for writing */
1088 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1092 strcpy(label, "yes");
1094 strcpy (label, "no");
1099 "graph: { title: \"ir graph of %s\"\n"
1100 "display_edge_labels: %s\n"
1101 "layoutalgorithm: mindepth\n"
1102 "manhattan_edges: yes\n"
1103 "port_sharing: no\n"
1104 "orientation: bottom_to_top\n"
1105 "classname 1: \"Data\"\n"
1106 "classname 2: \"Block\"\n"
1107 "classname 3: \"Entity type\"\n"
1108 "classname 4: \"Entity owner\"\n"
1109 "classname 5: \"Method Param\"\n"
1110 "classname 6: \"Method Res\"\n"
1111 "classname 7: \"Super\"\n"
1112 "classname 8: \"Union\"\n"
1113 "classname 9: \"Points-to\"\n"
1114 "classname 10: \"Array Element Type\"\n"
1115 "classname 11: \"Overwrites\"\n"
1116 "classname 12: \"Member\"\n"
1119 xfprintf (F, "\n"); /* a separator */
1124 xfprintf (F, "}\n"); /* print footer */
1125 fclose (F); /* close vcg file */
1128 /************************************************************************/
1129 /* routines to dump a graph, blocks as conventional nodes. */
1130 /************************************************************************/
1132 static int node_floats(ir_node *n) {
1133 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1134 (get_irg_pinned(current_ir_graph) == floats));
1138 dump_whole_node (ir_node *n, void* env) {
1140 if (!node_floats(n)) dump_ir_block_edge(n);
1141 dump_ir_data_edges(n);
1145 dump_ir_graph (ir_graph *irg)
1148 rem = current_ir_graph;
1149 current_ir_graph = irg;
1153 /* walk over the graph */
1154 /* dump_whole_node must be called in post visiting predecessors */
1155 irg_walk(irg->end, NULL, dump_whole_node, NULL);
1157 /* dump the out edges in a separate walk */
1158 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1159 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
1164 current_ir_graph = rem;
1167 /***********************************************************************/
1168 /* the following routines dump the nodes as attached to the blocks. */
1169 /***********************************************************************/
1172 dump_ir_blocks_nodes (ir_node *n, void *env) {
1173 ir_node *block = (ir_node *)env;
1175 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1177 dump_ir_data_edges(n);
1179 if (get_irn_op(n) == op_Bad)
1184 dump_ir_block (ir_node *block, void *env) {
1185 ir_graph *irg = (ir_graph *)env;
1187 if (get_irn_opcode(block) == iro_Block) {
1189 /* This is a block. So dump the vcg information to make a block. */
1190 xfprintf(F, "graph: { title: \"");
1191 PRINT_NODEID(block);
1192 fprintf(F, "\" label: \"");
1193 #ifdef DEBUG_libfirm
1194 xfprintf (F, "%ld", get_irn_node_nr(block));
1196 xfprintf (F, "%I", block->op->name);
1198 if (exc_normal != get_Block_exc (block))
1199 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1201 xfprintf(F, "\" status:clustered color:%s \n",
1202 get_Block_matured (block) ? "yellow" : "red");
1203 /* dump the blocks edges */
1204 dump_ir_data_edges(block);
1206 /* dump the nodes that go into the block */
1207 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1209 /* Close the vcg information for the block */
1210 xfprintf(F, "}\n\n");
1211 dump_const_node_local(block, NULL);
1217 dump_blockless_nodes (ir_node *n, void *env) {
1218 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1220 dump_ir_data_edges(n);
1221 dump_ir_block_edge(n);
1222 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1225 if (node_floats(n)) {
1227 dump_ir_data_edges(n);
1228 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1232 static void dump_ir_block_graph_2 (ir_graph *irg)
1235 /* walk over the blocks in the graph */
1236 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1238 /* dump all nodes that are not in a Block */
1239 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1241 /* dump the Bad node */
1243 dump_node(get_irg_bad(irg), NULL);
1247 dump_ir_block_graph (ir_graph *irg)
1250 rem = current_ir_graph;
1251 current_ir_graph = irg;
1255 dump_ir_block_graph_2 (irg);
1257 if (dump_loop_information_flag) dump_loop_info(irg);
1260 current_ir_graph = rem;
1264 /***********************************************************************/
1265 /* the following routines dump a control flow graph */
1266 /***********************************************************************/
1270 dump_block_to_cfg (ir_node *block, void *env) {
1274 if (get_irn_opcode(block) == iro_Block) {
1275 /* This is a block. Dump a node for the block. */
1276 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1277 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1279 if (exc_normal != get_Block_exc (block))
1280 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1282 xfprintf (F, "\" ");
1283 if (dump_dominator_information_flag)
1284 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1285 xfprintf (F, "}\n");
1286 /* Dump the edges */
1287 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1288 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1289 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1290 xfprintf (F, "edge: { sourcename: \"");
1291 PRINT_NODEID(block);
1292 fprintf (F, "\" targetname: \"");
1294 fprintf (F, "\" }\n");
1297 /* Dump dominator edge */
1298 if (dump_dominator_information_flag && get_Block_idom(block)) {
1299 pred = get_Block_idom(block);
1300 xfprintf (F, "edge: { sourcename: \"");
1301 PRINT_NODEID(block);
1302 fprintf (F, "\" targetname: \"");
1304 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1310 dump_cfg (ir_graph *irg)
1312 ir_graph *rem = current_ir_graph;
1313 int ddif = dump_dominator_information_flag;
1314 current_ir_graph = irg;
1315 vcg_open (irg, "-cfg");
1317 if (get_irg_dom_state(irg) != dom_consistent)
1318 dump_dominator_information_flag = 0;
1320 /* walk over the blocks in the graph */
1321 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1322 dump_ir_node (irg->bad);
1324 dump_dominator_information_flag = ddif;
1326 current_ir_graph = rem;
1330 /***********************************************************************/
1331 /* the following routine dumps all type information reachable from an */
1333 /***********************************************************************/
1337 dump_type_graph (ir_graph *irg)
1340 rem = current_ir_graph;
1341 current_ir_graph = irg;
1343 vcg_open (irg, "-type");
1345 /* walk over the blocks in the graph */
1346 type_walk_irg(irg, dump_type_info, NULL, NULL);
1347 /* The walker for the const code can be called several times for the
1348 same (sub) experssion. So that no nodes are dumped several times
1349 we decrease the visited flag of the corresponding graph after each
1350 walk. So now increase it finally. */
1351 inc_irg_visited(get_const_code_irg());
1354 current_ir_graph = rem;
1357 /***********************************************************************/
1358 /* the following routine dumps all type information */
1359 /***********************************************************************/
1363 dump_all_types (void)
1365 vcg_open_name ("All_types");
1366 type_walk(dump_type_info, NULL, NULL);
1367 inc_irg_visited(get_const_code_irg());
1372 dump_class_hierarchy (bool entities)
1374 vcg_open_name ("class_hierarchy");
1376 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1378 type_walk(dump_class_hierarchy_node, NULL, NULL);
1382 /***********************************************************************/
1383 /* dumps a graph with type information */
1384 /***********************************************************************/
1388 dump_ir_graph_w_types (ir_graph *irg)
1391 rem = current_ir_graph;
1392 current_ir_graph = irg;
1394 vcg_open (irg, "-all");
1396 /* dump common ir graph */
1397 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1398 /* dump type info */
1399 type_walk_irg(irg, dump_type_info, NULL, NULL);
1400 inc_irg_visited(get_const_code_irg());
1401 /* dump edges from graph to type info */
1402 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1405 current_ir_graph = rem;
1409 dump_ir_block_graph_w_types (ir_graph *irg)
1412 rem = current_ir_graph;
1413 current_ir_graph = irg;
1415 vcg_open (irg, "-all");
1417 /* dump common blocked ir graph */
1418 dump_ir_block_graph_2(irg);
1419 /* dump type info */
1420 type_walk_irg(irg, dump_type_info, NULL, NULL);
1421 inc_irg_visited(get_const_code_irg());
1422 /* dump edges from graph to type info */
1423 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1426 current_ir_graph = rem;
1429 /***********************************************************************/
1430 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1432 /* dump_ir_block_graph */
1434 /* dump_type_graph */
1435 /* dump_ir_graph_w_types */
1436 /***********************************************************************/
1437 void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
1439 for (i=0; i < get_irp_n_irgs(); i++) {
1440 dump_graph(get_irp_irg(i));
1445 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1446 abort with a segmentation fault. */
1447 void turn_off_edge_labels() {
1452 void dump_consts_local(bool b) {
1453 dump_const_local = b;
1456 void turn_off_constant_entity_values() {
1460 void dump_keepalive_edges(bool b) {
1464 void dump_out_edges() {
1465 dump_out_edge_flag = 1;
1468 void dump_dominator_information() {
1469 dump_dominator_information_flag = 1;
1472 void dump_loop_information() {
1473 dump_loop_information_flag = 1;
1476 void dont_dump_loop_information() {
1477 dump_loop_information_flag = 0;
1480 static void clear_link(ir_node * node, void * env) {
1481 set_irn_link(node, NULL);
1484 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1486 || node_floats(node)
1487 || get_irn_op(node) == op_Bad
1488 || get_irn_op(node) == op_Unknown) {
1489 pmap_entry * entry = pmap_find(map, current_ir_graph);
1491 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1493 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1495 pmap_insert(map, current_ir_graph, arr);
1498 ir_node * block = get_nodes_Block(node);
1499 set_irn_link(node, get_irn_link(block));
1500 set_irn_link(block, node);
1505 static void dump_cg_ir_block(ir_node * block, void * env) {
1507 pmap *irgmap = (pmap *)env;
1508 assert(is_Block(block));
1509 xfprintf(F, "graph: { title: \"");
1510 PRINT_NODEID(block);
1511 fprintf(F, "\" label: \"");
1512 #ifdef DEBUG_libfirm
1513 xfprintf (F, "%ld", get_irn_node_nr(block));
1515 xfprintf (F, "%I", block->op->name);
1517 if (exc_normal != get_Block_exc(block)) {
1518 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1521 xfprintf(F, "\" status:clustered color:%s \n",
1522 get_Block_matured(block) ? "yellow" : "red");
1524 /* dump the blocks edges */
1525 dump_ir_data_edges(block);
1527 /* dump the nodes that go into the block */
1528 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1529 dump_node(node, irgmap);
1530 dump_ir_data_edges(node);
1533 /* Close the vcg information for the block */
1534 xfprintf(F, "}\n\n");
1537 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1540 xfprintf(F, "graph: { title: \"%p\" label: \"%I\" status:clustered color:white \n",
1541 irg, get_entity_ident(get_irg_ent(irg)));
1543 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1544 ir_node * node = arr[i];
1545 if (is_Block(node)) {
1546 /* Dumps the block and all the nodes in the block , which are to
1547 be found in Block->link. */
1548 dump_cg_ir_block(node, irgmap);
1550 /* Nodes that are not in a Block. */
1551 dump_node(node, NULL);
1552 dump_ir_data_edges(node);
1555 /* Close the vcg information for the irg */
1556 xfprintf(F, "}\n\n");
1559 /* dump interprocedural graph with surrounding methods */
1560 void dump_cg_block_graph(ir_graph * irg) {
1561 pmap * map = pmap_create();
1562 pmap * map2 = pmap_create();
1567 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1568 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1569 pmap_insert(map2, entry->key, entry->value);
1570 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1571 d_cg_block_graph(entry->key, entry->value, map2);
1572 DEL_ARR_F(entry->value);
1578 if (dump_loop_information_flag) dump_loop_info(irg);
1582 static void collect_node(ir_node * node, void *env) {
1584 || node_floats(node)
1585 || get_irn_op(node) == op_Bad
1586 || get_irn_op(node) == op_Unknown) {
1587 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1588 ARR_APP1(ir_node *, arr, node);
1589 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1591 ir_node * block = get_nodes_Block(node);
1592 set_irn_link(node, get_irn_link(block));
1593 set_irn_link(block, node);
1597 /* Links all nodes that have the block field set in the link field of
1598 the block. Adds all blocks and nodes not associated with a block
1599 in a array in irg->link. */
1600 static void collect_nodes() {
1602 for (i = 0; i < get_irp_n_irgs(); i++)
1603 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1604 cg_walk(clear_link, collect_node, NULL);
1607 static void dump_graphs() {
1609 for (i = 0; i < get_irp_n_irgs(); i++) {
1610 current_ir_graph = get_irp_irg(i);
1611 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1615 /* Dump all irgs in interprocedural view to a single file. */
1616 void dump_all_cg_block_graph() {
1618 int rem_view = interprocedural_view;
1619 interprocedural_view = 1;
1620 vcg_open_name ("All_graphs");
1625 if (dump_loop_information_flag)
1626 for (i = 0; i < get_irp_n_irgs(); i++)
1627 dump_loop_info(get_irp_irg(i));
1630 interprocedural_view = rem_view;
1633 /* dump interprocedural block graph with surrounding methods */
1634 void dump_cg_graph(ir_graph * irg) {
1635 pmap * map = pmap_create();
1636 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1640 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1641 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1642 pmap_insert(map2, entry->key, entry->value);
1643 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1644 ir_node ** arr = entry->value;
1646 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1648 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1649 irg_ident, irg_ident);
1651 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1652 ir_node * node = arr[i];
1653 dump_node(node, map2);
1654 dump_ir_data_edges(node);
1655 if (is_Block(node)) {
1656 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1657 dump_node(node, map2);
1658 dump_ir_block_edge(node);
1659 dump_ir_data_edges(node);
1666 /* Close the vcg information for the irg */
1667 xfprintf(F, "}\n\n");