1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
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(n) == 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));
177 static void dump_node_loop_info(ir_node *n) {
178 // if (get_irn_loop(n))
179 // xfprintf(F, "\n in loop %d", get_loop_depth(get_irn_loop(n)));
183 dump_node_nodeattr (ir_node *n)
185 switch (n->op->code) {
187 if (false && interprocedural_view) {
188 xfprintf (F, "%I", get_entity_ident(get_irg_ent(current_ir_graph)));
192 if (n->in[1]->op->code == iro_Cmp) {
193 xfprintf (F, "%s", get_pnc_string(n->attr.proj));
195 xfprintf (F, "%ld", n->attr.proj);
199 xfprintf (F, "%ld", n->attr.filter.proj);
202 assert(get_kind(get_Sel_entity(n)) == k_entity);
203 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
211 dump_node_vcgattr (ir_node *n)
213 switch (n->op->code) {
220 xfprintf (F, "color: blue");
223 xfprintf (F, "color: lightyellow");
226 xfprintf (F, "color: green");
232 xfprintf (F, "color: yellow");
235 xfprintf (F, DEFAULT_NODE_ATTR);
239 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
240 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
243 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
244 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
245 if (is_ip_cfop(pred)) {
246 ir_graph *irg = get_ip_cfop_irg(pred);
247 if (pmap_find(irgmap, irg) == NULL) return true;
256 bool is_constlike_node(ir_node *n) {
257 ir_op *op = get_irn_op(n);
258 return (op == op_Const || op == op_Bad || op == op_SymConst);
262 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
264 if (!dump_const_local_set()) return;
265 /* Use visited flag to avoid outputting nodes twice.
266 initialize it first. */
267 for (i = 0; i < get_irn_arity(n); i++) {
268 ir_node *con = get_irn_n(n, i);
269 if (is_constlike_node(con)) {
270 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
271 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
274 for (i = 0; i < get_irn_arity(n); i++) {
275 ir_node *con = get_irn_n(n, i);
276 if (is_constlike_node(con) && irn_not_visited(con)) {
277 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
278 mark_irn_visited(con);
279 /* Generate a new name for the node by appending the names of
281 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); PRINT_NODEID(con);
282 fprintf(F, "\" label: \"");
283 dump_node_opcode(con);
284 dump_node_mode (con);
286 dump_node_nodeattr(con);
288 xfprintf (F, " %ld", get_irn_node_nr(con));
291 dump_node_vcgattr(con);
298 dump_node (ir_node *n, pmap * map) {
299 if (dump_const_local_set() && is_constlike_node(n)) return;
302 xfprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
307 dump_node_nodeattr(n);
309 xfprintf (F, " %ld", get_irn_node_nr(n));
312 dump_node_vcgattr(n);
314 dump_const_node_local(n, map);
318 dump_ir_node (ir_node *n)
321 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: ");
323 switch (n->op->code) { /* node label */
325 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
326 xfprintf (F, DEFAULT_NODE_ATTR);
333 xfprintf (F, "\"%I\" color: blue ", get_irn_opident(n));
334 xfprintf (F, DEFAULT_NODE_ATTR);
337 xfprintf (F, "\"%I\" color: lightyellow ", get_irn_opident(n));
338 xfprintf (F, DEFAULT_NODE_ATTR);
341 xfprintf (F, "\"%I%I\" color: green", get_irn_opident(n), get_irn_modeident(n));
342 if (get_irn_modecode(n) == irm_M)
343 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
345 xfprintf (F, DEFAULT_NODE_ATTR);
348 xfprintf (F, "\"%v%I\" color: yellow ", n->attr.con, get_irn_modeident(n));
349 xfprintf (F, DEFAULT_NODE_ATTR);
352 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
353 xfprintf (F, DEFAULT_NODE_ATTR);
356 if (n->in[1]->op->code == iro_Cmp) {
357 xfprintf (F, "\"%I%I %s\" color: yellow", get_irn_opident(n), get_irn_modeident(n),
358 get_pnc_string(n->attr.proj));
360 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.proj);
362 xfprintf (F, DEFAULT_NODE_ATTR);
365 xfprintf (F, "\"%I%I %ld\"", get_irn_opident(n), get_irn_modeident(n), n->attr.filter.proj);
366 xfprintf (F, DEFAULT_NODE_ATTR);
369 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
370 xfprintf (F, DEFAULT_NODE_ATTR);
373 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
374 xfprintf (F, DEFAULT_NODE_ATTR);
377 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
378 xfprintf (F, DEFAULT_NODE_ATTR);
381 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
382 xfprintf (F, DEFAULT_NODE_ATTR);
385 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
386 xfprintf (F, DEFAULT_NODE_ATTR);
389 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
390 xfprintf (F, DEFAULT_NODE_ATTR);
393 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
394 xfprintf (F, DEFAULT_NODE_ATTR);
397 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
398 xfprintf (F, DEFAULT_NODE_ATTR);
401 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
402 xfprintf (F, DEFAULT_NODE_ATTR);
405 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
406 xfprintf (F, DEFAULT_NODE_ATTR);
409 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
410 xfprintf (F, DEFAULT_NODE_ATTR);
413 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
414 xfprintf (F, DEFAULT_NODE_ATTR);
417 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
418 xfprintf (F, DEFAULT_NODE_ATTR);
421 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
422 xfprintf (F, DEFAULT_NODE_ATTR);
425 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
426 xfprintf (F, DEFAULT_NODE_ATTR);
429 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
430 xfprintf (F, DEFAULT_NODE_ATTR);
433 xfprintf (F, "\"%I\"", get_irn_opident(n));
434 xfprintf (F, DEFAULT_NODE_ATTR);
437 xfprintf (F, "\"%I\"", get_irn_opident(n));
438 xfprintf (F, DEFAULT_NODE_ATTR);
441 xfprintf (F, "\"%I\"", get_irn_opident(n));
442 xfprintf (F, DEFAULT_NODE_ATTR);
445 xfprintf (F, "\"%I\"", get_irn_opident(n));
446 xfprintf (F, DEFAULT_NODE_ATTR);
449 xfprintf (F, "\"%I\"", get_irn_opident(n));
450 xfprintf (F, DEFAULT_NODE_ATTR);
453 xfprintf (F, "\"%I\"", get_irn_opident(n));
454 xfprintf (F, DEFAULT_NODE_ATTR);
457 xfprintf (F, "\"%I%I\"", get_irn_opident(n), get_irn_modeident(n));
458 xfprintf (F, DEFAULT_NODE_ATTR);
462 xfprintf (F, "\"%R\"", n);
463 xfprintf (F, DEFAULT_NODE_ATTR);
466 xfprintf (F, "\"%I\" ", get_irn_opident(n));
467 xfprintf (F, DEFAULT_NODE_ATTR);
470 assert(get_kind(get_Sel_entity(n)) == k_entity);
471 xfprintf (F, "\"%I ", get_irn_opident(n));
472 xfprintf (F, "%I", get_entity_ident(get_Sel_entity(n)));
473 xfprintf (F, DEFAULT_NODE_ATTR);
476 assert(get_kind(get_SymConst_type(n)) == k_type);
477 assert(get_type_ident(get_SymConst_type(n)));
478 xfprintf (F, "\"%s ", get_type_name(get_SymConst_type(n)));
479 switch (n->attr.i.num){
481 xfprintf (F, "tag\" ");
484 xfprintf (F, "size\" ");
490 xfprintf (F, DEFAULT_NODE_ATTR);
493 xfprintf (F, "\"%I\" ", get_irn_opident(n));
494 xfprintf (F, DEFAULT_NODE_ATTR " color: green");
497 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
498 xfprintf (F, DEFAULT_NODE_ATTR);
501 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
502 xfprintf (F, DEFAULT_NODE_ATTR);
505 xfprintf (F, "\"%I%I\" ", get_irn_opident(n), get_irn_modeident(n));
507 xfprintf (F, "}\n"); /* footer */
511 /* dump the edge to the block this node belongs to */
513 dump_ir_block_edge(ir_node *n) {
514 if (dump_const_local_set() && is_constlike_node(n)) return;
515 if (is_no_Block(n)) {
516 xfprintf (F, "edge: { sourcename: \"");
518 xfprintf (F, "\" targetname: \"");
519 PRINT_NODEID(get_nodes_Block(n));
520 xfprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
524 static void print_edge_vcgattr(ir_node *from, int to) {
527 if (is_backedge(from, to)) xfprintf (F, BACK_EDGE_ATTR);
529 switch (get_irn_opcode(from)) {
531 xfprintf (F, CF_EDGE_ATTR);
533 case iro_Start: break;
536 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
537 xfprintf (F, CF_EDGE_ATTR);
538 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
539 xfprintf (F, MEM_EDGE_ATTR);
542 case iro_EndReg: break;
543 case iro_EndExcept: break;
545 case iro_Break: break;
546 case iro_Cond: break;
549 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
551 case iro_Const: break;
552 case iro_SymConst:break;
555 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
557 case iro_CallBegin: break;
560 case iro_Minus: break;
566 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
574 case iro_Shrs: break;
577 case iro_Conv: break;
579 if (get_irn_modecode(from) == irm_M) xfprintf (F, MEM_EDGE_ATTR);
585 if (to == 0) xfprintf (F, MEM_EDGE_ATTR);
588 xfprintf (F, MEM_EDGE_ATTR);
590 case iro_Tuple: break;
593 switch (get_irn_modecode(from)) {
595 xfprintf (F, CF_EDGE_ATTR);
598 xfprintf (F, MEM_EDGE_ATTR);
604 case iro_Unknown: break;
611 /* dump edges to our inputs */
613 dump_ir_data_edges(ir_node *n) {
614 int i, visited = get_irn_visited(n);
616 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
619 for (i = 0; i < get_irn_arity(n); i++) {
620 ir_node * pred = get_irn_n(n, i);
622 if ((interprocedural_view && get_irn_visited(pred) < visited))
623 continue; /* pred not dumped */
624 if (is_backedge(n, i))
625 fprintf (F, "backedge: {sourcename: \"");
627 fprintf (F, "edge: {sourcename: \"");
629 fprintf (F, "\" targetname: \"");
630 if ((dump_const_local_set()) && is_constlike_node(pred))
634 fprintf (F, " label: \"%d\" ", i);
635 print_edge_vcgattr(n, i);
642 dump_out_edge (ir_node *n, void* env) {
644 for (i = 0; i < get_irn_n_outs(n); i++) {
645 assert(get_irn_out(n, i));
646 fprintf (F, "edge: {sourcename: \"");
648 fprintf (F, "\" targetname: \"");
649 PRINT_NODEID(get_irn_out(n, i));
650 fprintf (F, "\" color: red linestyle: dashed");
656 dump_loop_node_edge (ir_loop *loop, int i) {
658 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", loop);
659 PRINT_NODEID(get_loop_node(loop, i));
660 fprintf (F, "\" color: green");
665 void dump_loops (ir_loop *loop) {
667 /* dump this loop node */
668 xfprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
669 loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
670 /* dump edges to nodes in loop -- only if it is a real loop */
671 if (get_loop_depth(loop) != 0) {
672 for (i = 0; i < get_loop_n_nodes(loop); i++) {
673 dump_loop_node_edge(loop, i);
676 for (i = 0; i < get_loop_n_sons(loop); i++) {
677 dump_loops(get_loop_son(loop, i));
682 void dump_loop_info(ir_graph *irg) {
683 ir_graph *rem = current_ir_graph;
684 current_ir_graph = irg;
686 if (get_irg_loop(irg))
687 dump_loops(get_irg_loop(irg));
689 current_ir_graph = rem;
693 /* dumps the edges between nodes and their type or entity attributes. */
694 static void dump_node2type_edges (ir_node *n, void *env)
698 switch (get_irn_opcode(n)) {
700 /* @@@ some consts have an entity */
703 if ( (get_SymConst_kind(n) == type_tag)
704 || (get_SymConst_kind(n) == size)) {
705 xfprintf (F, "edge: { sourcename: \"");
707 fprintf (F, "\" targetname: \"%p\" "
708 NODE2TYPE_EDGE_ATTR "}\n", get_SymConst_type(n));
712 xfprintf (F, "edge: { sourcename: \"");
714 fprintf (F, "\" targetname: \"%p\" "
715 NODE2TYPE_EDGE_ATTR "}\n", get_Sel_entity(n));
718 xfprintf (F, "edge: { sourcename: \"");
720 fprintf (F, "\" targetname: \"%p\" "
721 NODE2TYPE_EDGE_ATTR "}\n", get_Call_type(n));
724 xfprintf (F, "edge: { sourcename: \"");
726 fprintf (F, "\" targetname: \"%p\" "
727 NODE2TYPE_EDGE_ATTR "}\n", get_Alloc_type(n));
730 xfprintf (F, "edge: { sourcename: \"");
732 fprintf (F, "\" targetname: \"%p\" "
733 NODE2TYPE_EDGE_ATTR "}\n", get_Free_type(n));
741 static void dump_const_expression(ir_node *value) {
742 ir_graph *rem = current_ir_graph;
743 int rem_dump_const_local = dump_const_local;
744 dump_const_local = 0;
745 current_ir_graph = get_const_code_irg();
746 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
747 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
748 current_ir_graph = rem;
749 dump_const_local = rem_dump_const_local;
753 static void print_type_info(type *tp) {
754 if (get_type_state(tp) == layout_undefined) {
755 xfprintf(F, "state: layout_undefined\n");
757 xfprintf(F, "state: layout_fixed,\n");
759 if (get_type_mode(tp))
760 xfprintf(F, "mode: %s,\n", get_mode_name(get_type_mode(tp)));
761 xfprintf(F, "size: %dB,\n", get_type_size(tp));
765 static void print_typespecific_info(type *tp) {
766 switch (get_type_tpop_code(tp)) {
769 if(existent == get_class_peculiarity(tp))
770 xfprintf (F, " " TYPE_CLASS_NODE_ATTR);
772 xfprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
776 xfprintf (F, " " TYPE_METH_NODE_ATTR);
787 case tpo_enumeration:
800 static void print_type_node(type *tp) {
801 xfprintf (F, "node: {title: \"%p\" ", tp);
802 xfprintf (F, "label: \"%I %I\"", get_type_tpop_nameid(tp), get_type_ident(tp));
803 xfprintf (F, "info1: \"");
806 print_typespecific_info(tp);
810 void dump_entity_node(entity *ent) {
811 xfprintf (F, "node: {title: \"%p\" ", ent);
812 xfprintf (F, DEFAULT_TYPE_ATTRIBUTE);
813 xfprintf (F, "label: ");
814 xfprintf (F, "\"ent %I\" " ENTITY_NODE_ATTR , get_entity_ident(ent));
815 switch (get_entity_allocation(ent)) {
816 case dynamic_allocated: fprintf (F, " info1:\"dynamic allocated\n"); break;
817 case automatic_allocated: fprintf (F, " info1:\"automatic allocated\n"); break;
818 case static_allocated: fprintf (F, " info1:\"static allocated\n"); break;
820 switch (get_entity_visibility(ent)) {
821 case local: fprintf (F, "local\n"); break;
822 case external_visible: fprintf (F, "external_visible\n"); break;
823 case external_allocated: fprintf (F, "external_allocate\n"); break;
825 switch (get_entity_variability(ent)) {
826 case uninitialized: fprintf (F, "uninitialized\n");break;
827 case initialized: fprintf (F, "initialized\n"); break;
828 case part_constant: fprintf (F, "part_constant\n");break;
829 case constant: fprintf (F, "constant\n"); break;
831 switch (get_entity_volatility(ent)) {
832 case non_volatile: fprintf (F, "non_volatile\n"); break;
833 case is_volatile: fprintf (F, "is_volatile\n"); break;
835 switch (get_entity_peculiarity(ent)) {
836 case description: fprintf (F, "description\n"); break;
837 case inherited: fprintf (F, "inherited\n"); break;
838 case existent: fprintf (F, "existent\n"); break;
840 if (is_method_type(get_entity_type(ent)))
841 xfprintf (F, "\n irg = %p ", get_entity_irg(ent));
842 xfprintf(F, "\"}\n");
845 /* dumps a type or entity and it's edges. */
847 dump_type_info (type_or_ent *tore, void *env) {
848 int i = 0; /* to shutup gcc */
850 /* dump this type or entity */
852 switch (get_kind(tore)) {
855 entity *ent = (entity *)tore;
858 dump_entity_node(ent);
860 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
861 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
862 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
863 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
864 ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
865 if(is_class_type(get_entity_owner(ent))) {
866 for(i = 0; i < get_entity_n_overwrites(ent); i++)
867 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
868 ENT_OVERWRITES_EDGE_ATTR "}\n",
869 ent, get_entity_overwrites(ent, i));
871 /* attached subgraphs */
872 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
873 if (is_atomic_entity(ent)) {
874 value = get_atomic_ent_value(ent);
875 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
877 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
878 dump_const_expression(value);
880 if (is_compound_entity(ent)) {
881 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
882 value = get_compound_ent_value(ent, i);
883 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"", ent);
885 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR " %d \"}\n", i);
886 dump_const_expression(value);
887 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
888 ENT_CORR_EDGE_ATTR "}\n", ent,
889 get_compound_ent_value_member(ent, i), i);
896 type *tp = (type *)tore;
898 /* and now the edges */
899 switch (get_type_tpop_code(tp)) {
902 for (i=0; i < get_class_n_supertypes(tp); i++)
903 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
904 TYPE_SUPER_EDGE_ATTR "}\n",
905 tp, get_class_supertype(tp, i));
906 for (i=0; i < get_class_n_members(tp); i++)
907 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
908 TYPE_MEMBER_EDGE_ATTR "}\n",
909 tp, get_class_member(tp, i));
913 for (i=0; i < get_struct_n_members(tp); i++)
914 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
915 TYPE_MEMBER_EDGE_ATTR "}\n",
916 tp, get_struct_member(tp, i));
920 for (i = 0; i < get_method_n_params(tp); i++)
921 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
922 METH_PAR_EDGE_ATTR "}\n",
923 tp, get_method_param_type(tp, i), i);
924 for (i = 0; i < get_method_n_ress(tp); i++)
925 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
926 METH_RES_EDGE_ATTR "}\n",
927 tp, get_method_res_type(tp, i), i);
931 for (i = 0; i < get_union_n_members(tp); i++)
932 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
933 "label: \"\"f" UNION_EDGE_ATTR "}\n",
934 tp, get_union_member(tp, i));
938 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
939 ARR_ELT_TYPE_EDGE_ATTR "}\n", tp, get_array_element_type(tp), i);
940 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
941 ARR_ENT_EDGE_ATTR "}\n", tp, get_array_element_entity(tp), i);
943 case tpo_enumeration:
948 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
949 PTR_PTS_TO_EDGE_ATTR "}\n", tp,
950 get_pointer_points_to_type(tp), i);
958 break; /* case k_type */
961 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
963 } /* switch kind_or_entity */
966 /* dumps a class type node and a superclass edge.
967 If env != null dumps entities of classes and overwrites edges. */
969 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
970 int i = 0; /* to shutup gcc */
972 /* dump this type or entity */
973 switch (get_kind(tore)) {
975 entity *ent = (entity *)tore;
976 if ((env) && is_class_type(get_entity_owner(ent))) {
978 dump_entity_node(ent);
980 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
981 TYPE_MEMBER_EDGE_ATTR "}\n", get_entity_owner(ent), ent);
982 for(i = 0; i < get_entity_n_overwrites(ent); i++)
983 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
984 ENT_OVERWRITES_EDGE_ATTR "}\n",
985 ent, get_entity_overwrites(ent, i));
987 } break; /* case k_entity */
990 type *tp = (type *)tore;
991 switch (get_type_tpop_code(tp)) {
994 /* and now the edges */
995 for (i=0; i < get_class_n_supertypes(tp); i++)
996 xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
997 TYPE_SUPER_EDGE_ATTR "}\n",
998 tp, get_class_supertype(tp, i));
1003 break; /* case k_type */
1006 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1008 } /* switch kind_or_entity */
1011 /************************************************************************/
1012 /* open and close vcg file */
1013 /************************************************************************/
1015 static void vcg_open (ir_graph *irg, char *suffix) {
1016 char *fname; /* filename to put the vcg information in */
1023 /** open file for vcg graph */
1024 ent = get_irg_ent(irg);
1025 id = ent->ld_name ? ent->ld_name : ent->name;
1026 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
1027 len = id_to_strlen (id);
1028 cp = id_to_str (id);
1029 if (dump_file_suffix)
1030 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
1032 fname = malloc (len + 5 + strlen(suffix));
1033 strncpy (fname, cp, len); /* copy the filename */
1035 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
1036 strcat (fname, suffix); /* append file suffix */
1037 strcat (fname, ".vcg"); /* append the .vcg suffix */
1038 F = fopen (fname, "w"); /* open file for writing */
1040 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1044 strcpy(label, "yes");
1046 strcpy (label, "no");
1051 "graph: { title: \"ir graph of %s\"\n"
1052 "display_edge_labels: %s\n"
1053 "layoutalgorithm: mindepth\n"
1054 "manhattan_edges: yes\n"
1055 "port_sharing: no\n"
1056 "orientation: bottom_to_top\n"
1057 "classname 1: \"Data\"\n"
1058 "classname 2: \"Block\"\n"
1059 "classname 3: \"Entity type\""
1060 "classname 4: \"Entity owner\""
1061 "classname 5: \"Method Param\""
1062 "classname 6: \"Method Res\""
1063 "classname 7: \"Super\""
1064 "classname 8: \"Union\""
1065 "classname 9: \"Points-to\""
1066 "classname 10: \"Array Element Type\""
1067 "classname 11: \"Overwrites\""
1068 "classname 12: \"Member\""
1071 xfprintf (F, "\n"); /* a separator */
1074 static void vcg_open_name (const char *name) {
1075 char *fname; /* filename to put the vcg information in */
1079 /** open file for vcg graph */
1081 fname = malloc (len + 5);
1082 if (dump_file_suffix)
1083 fname = malloc (len + 5 + strlen(dump_file_suffix));
1085 fname = malloc (len + 5);
1086 strcpy (fname, name); /* copy the filename */
1087 if (dump_file_suffix) strcat (fname, dump_file_suffix);
1088 strcat (fname, ".vcg"); /* append the .vcg suffix */
1089 F = fopen (fname, "w"); /* open file for writing */
1091 panic ("cannot open %s for writing (%m)", fname); /* not reached */
1095 strcpy(label, "yes");
1097 strcpy (label, "no");
1102 "graph: { title: \"ir graph of %s\"\n"
1103 "display_edge_labels: %s\n"
1104 "layoutalgorithm: mindepth\n"
1105 "manhattan_edges: yes\n"
1106 "port_sharing: no\n"
1107 "orientation: bottom_to_top\n"
1108 "classname 1: \"Data\"\n"
1109 "classname 2: \"Block\"\n"
1110 "classname 3: \"Entity type\"\n"
1111 "classname 4: \"Entity owner\"\n"
1112 "classname 5: \"Method Param\"\n"
1113 "classname 6: \"Method Res\"\n"
1114 "classname 7: \"Super\"\n"
1115 "classname 8: \"Union\"\n"
1116 "classname 9: \"Points-to\"\n"
1117 "classname 10: \"Array Element Type\"\n"
1118 "classname 11: \"Overwrites\"\n"
1119 "classname 12: \"Member\"\n"
1122 xfprintf (F, "\n"); /* a separator */
1127 xfprintf (F, "}\n"); /* print footer */
1128 fclose (F); /* close vcg file */
1131 /************************************************************************/
1132 /* routines to dump a graph, blocks as conventional nodes. */
1133 /************************************************************************/
1135 static int node_floats(ir_node *n) {
1136 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1137 (get_irg_pinned(current_ir_graph) == floats));
1141 dump_whole_node (ir_node *n, void* env) {
1143 if (!node_floats(n)) dump_ir_block_edge(n);
1144 dump_ir_data_edges(n);
1148 dump_ir_graph (ir_graph *irg)
1151 rem = current_ir_graph;
1152 current_ir_graph = irg;
1156 /* walk over the graph */
1157 /* dump_whole_node must be called in post visiting predecessors */
1158 irg_walk(irg->end, NULL, dump_whole_node, NULL);
1160 /* dump the out edges in a separate walk */
1161 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1162 irg_out_walk(irg->start, dump_out_edge, NULL, NULL);
1167 current_ir_graph = rem;
1170 /***********************************************************************/
1171 /* the following routines dump the nodes as attached to the blocks. */
1172 /***********************************************************************/
1175 dump_ir_blocks_nodes (ir_node *n, void *env) {
1176 ir_node *block = (ir_node *)env;
1178 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1180 dump_ir_data_edges(n);
1182 if (get_irn_op(n) == op_Bad)
1187 dump_ir_block (ir_node *block, void *env) {
1188 ir_graph *irg = (ir_graph *)env;
1190 if (get_irn_opcode(block) == iro_Block) {
1192 /* This is a block. So dump the vcg information to make a block. */
1193 xfprintf(F, "graph: { title: \"");
1194 PRINT_NODEID(block);
1195 fprintf(F, "\" label: \"");
1196 #ifdef DEBUG_libfirm
1197 xfprintf (F, "%ld", get_irn_node_nr(block));
1199 xfprintf (F, "%I", block->op->name);
1201 if (exc_normal != get_Block_exc (block))
1202 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1204 xfprintf(F, "\" status:clustered color:%s \n",
1205 get_Block_matured (block) ? "yellow" : "red");
1206 /* dump the blocks edges */
1207 dump_ir_data_edges(block);
1209 /* dump the nodes that go into the block */
1210 irg_walk(irg->end, dump_ir_blocks_nodes, NULL, block);
1212 /* Close the vcg information for the block */
1213 xfprintf(F, "}\n\n");
1214 dump_const_node_local(block, NULL);
1220 dump_blockless_nodes (ir_node *n, void *env) {
1221 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1223 dump_ir_data_edges(n);
1224 dump_ir_block_edge(n);
1225 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1228 if (node_floats(n)) {
1230 dump_ir_data_edges(n);
1231 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1235 static void dump_ir_block_graph_2 (ir_graph *irg)
1238 /* walk over the blocks in the graph */
1239 irg_block_walk(irg->end, dump_ir_block, NULL, irg);
1241 /* dump all nodes that are not in a Block */
1242 irg_walk(irg->end, dump_blockless_nodes, NULL, NULL);
1244 /* dump the Bad node */
1246 dump_node(get_irg_bad(irg), NULL);
1250 dump_ir_block_graph (ir_graph *irg)
1253 rem = current_ir_graph;
1254 current_ir_graph = irg;
1258 dump_ir_block_graph_2 (irg);
1260 if (dump_loop_information_flag) dump_loop_info(irg);
1263 current_ir_graph = rem;
1267 /***********************************************************************/
1268 /* the following routines dump a control flow graph */
1269 /***********************************************************************/
1273 dump_block_to_cfg (ir_node *block, void *env) {
1277 if (get_irn_opcode(block) == iro_Block) {
1278 /* This is a block. Dump a node for the block. */
1279 xfprintf (F, "node: {title:\""); PRINT_NODEID(block);
1280 xfprintf (F, "\" label: \"%I ", block->op->name); PRINT_NODEID(block);
1282 if (exc_normal != get_Block_exc (block))
1283 xfprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1285 xfprintf (F, "\" ");
1286 if (dump_dominator_information_flag)
1287 xfprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1288 xfprintf (F, "}\n");
1289 /* Dump the edges */
1290 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1291 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1292 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1293 xfprintf (F, "edge: { sourcename: \"");
1294 PRINT_NODEID(block);
1295 fprintf (F, "\" targetname: \"");
1297 fprintf (F, "\" }\n");
1300 /* Dump dominator edge */
1301 if (dump_dominator_information_flag && get_Block_idom(block)) {
1302 pred = get_Block_idom(block);
1303 xfprintf (F, "edge: { sourcename: \"");
1304 PRINT_NODEID(block);
1305 fprintf (F, "\" targetname: \"");
1307 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1313 dump_cfg (ir_graph *irg)
1315 ir_graph *rem = current_ir_graph;
1316 int ddif = dump_dominator_information_flag;
1317 current_ir_graph = irg;
1318 vcg_open (irg, "-cfg");
1320 if (get_irg_dom_state(irg) != dom_consistent)
1321 dump_dominator_information_flag = 0;
1323 /* walk over the blocks in the graph */
1324 irg_block_walk(irg->end, dump_block_to_cfg, NULL, NULL);
1325 dump_ir_node (irg->bad);
1327 dump_dominator_information_flag = ddif;
1329 current_ir_graph = rem;
1333 /***********************************************************************/
1334 /* the following routine dumps all type information reachable from an */
1336 /***********************************************************************/
1340 dump_type_graph (ir_graph *irg)
1343 rem = current_ir_graph;
1344 current_ir_graph = irg;
1346 vcg_open (irg, "-type");
1348 /* walk over the blocks in the graph */
1349 type_walk_irg(irg, dump_type_info, NULL, NULL);
1350 /* The walker for the const code can be called several times for the
1351 same (sub) experssion. So that no nodes are dumped several times
1352 we decrease the visited flag of the corresponding graph after each
1353 walk. So now increase it finally. */
1354 inc_irg_visited(get_const_code_irg());
1357 current_ir_graph = rem;
1360 /***********************************************************************/
1361 /* the following routine dumps all type information */
1362 /***********************************************************************/
1366 dump_all_types (void)
1368 vcg_open_name ("All_types");
1369 type_walk(dump_type_info, NULL, NULL);
1370 inc_irg_visited(get_const_code_irg());
1375 dump_class_hierarchy (bool entities)
1377 vcg_open_name ("class_hierarchy");
1379 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1381 type_walk(dump_class_hierarchy_node, NULL, NULL);
1385 /***********************************************************************/
1386 /* dumps a graph with type information */
1387 /***********************************************************************/
1391 dump_ir_graph_w_types (ir_graph *irg)
1394 rem = current_ir_graph;
1395 current_ir_graph = irg;
1397 vcg_open (irg, "-all");
1399 /* dump common ir graph */
1400 irg_walk(irg->end, dump_whole_node, NULL, NULL);
1401 /* dump type info */
1402 type_walk_irg(irg, dump_type_info, NULL, NULL);
1403 inc_irg_visited(get_const_code_irg());
1404 /* dump edges from graph to type info */
1405 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1408 current_ir_graph = rem;
1412 dump_ir_block_graph_w_types (ir_graph *irg)
1415 rem = current_ir_graph;
1416 current_ir_graph = irg;
1418 vcg_open (irg, "-all");
1420 /* dump common blocked ir graph */
1421 dump_ir_block_graph_2(irg);
1422 /* dump type info */
1423 type_walk_irg(irg, dump_type_info, NULL, NULL);
1424 inc_irg_visited(get_const_code_irg());
1425 /* dump edges from graph to type info */
1426 irg_walk(irg->end, dump_node2type_edges, NULL, NULL);
1429 current_ir_graph = rem;
1432 /***********************************************************************/
1433 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1435 /* dump_ir_block_graph */
1437 /* dump_type_graph */
1438 /* dump_ir_graph_w_types */
1439 /***********************************************************************/
1440 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1442 for (i=0; i < get_irp_n_irgs(); i++) {
1443 dump_graph(get_irp_irg(i));
1448 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1449 abort with a segmentation fault. */
1450 void turn_off_edge_labels() {
1455 void dump_consts_local(bool b) {
1456 dump_const_local = b;
1459 void turn_off_constant_entity_values() {
1463 void dump_keepalive_edges(bool b) {
1467 void dump_out_edges() {
1468 dump_out_edge_flag = 1;
1471 void dump_dominator_information() {
1472 dump_dominator_information_flag = 1;
1475 void dump_loop_information() {
1476 dump_loop_information_flag = 1;
1479 void dont_dump_loop_information() {
1480 dump_loop_information_flag = 0;
1483 static void clear_link(ir_node * node, void * env) {
1484 set_irn_link(node, NULL);
1487 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1489 || node_floats(node)
1490 || get_irn_op(node) == op_Bad
1491 || get_irn_op(node) == op_Unknown) {
1492 pmap_entry * entry = pmap_find(map, current_ir_graph);
1494 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1496 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1498 pmap_insert(map, current_ir_graph, arr);
1501 ir_node * block = get_nodes_Block(node);
1502 set_irn_link(node, get_irn_link(block));
1503 set_irn_link(block, node);
1508 static void dump_cg_ir_block(ir_node * block, void * env) {
1510 pmap *irgmap = (pmap *)env;
1511 assert(is_Block(block));
1512 xfprintf(F, "graph: { title: \"");
1513 PRINT_NODEID(block);
1514 fprintf(F, "\" label: \"");
1515 #ifdef DEBUG_libfirm
1516 xfprintf (F, "%ld", get_irn_node_nr(block));
1518 xfprintf (F, "%I", block->op->name);
1520 if (exc_normal != get_Block_exc(block)) {
1521 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1524 xfprintf(F, "\" status:clustered color:%s \n",
1525 get_Block_matured(block) ? "yellow" : "red");
1527 /* dump the blocks edges */
1528 dump_ir_data_edges(block);
1530 /* dump the nodes that go into the block */
1531 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1532 dump_node(node, irgmap);
1533 dump_ir_data_edges(node);
1536 /* Close the vcg information for the block */
1537 xfprintf(F, "}\n\n");
1540 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1543 xfprintf(F, "graph: { title: \"%p\" label: \"%I\" status:clustered color:white \n",
1544 irg, get_entity_ident(get_irg_ent(irg)));
1546 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1547 ir_node * node = arr[i];
1548 if (is_Block(node)) {
1549 /* Dumps the block and all the nodes in the block , which are to
1550 be found in Block->link. */
1551 dump_cg_ir_block(node, irgmap);
1553 /* Nodes that are not in a Block. */
1554 dump_node(node, NULL);
1555 dump_ir_data_edges(node);
1558 /* Close the vcg information for the irg */
1559 xfprintf(F, "}\n\n");
1562 /* dump interprocedural graph with surrounding methods */
1563 void dump_cg_block_graph(ir_graph * irg) {
1564 pmap * map = pmap_create();
1565 pmap * map2 = pmap_create();
1570 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1571 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1572 pmap_insert(map2, entry->key, entry->value);
1573 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1574 d_cg_block_graph(entry->key, entry->value, map2);
1575 DEL_ARR_F(entry->value);
1581 if (dump_loop_information_flag) dump_loop_info(irg);
1585 static void collect_node(ir_node * node, void *env) {
1587 || node_floats(node)
1588 || get_irn_op(node) == op_Bad
1589 || get_irn_op(node) == op_Unknown) {
1590 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1591 ARR_APP1(ir_node *, arr, node);
1592 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1594 ir_node * block = get_nodes_Block(node);
1595 set_irn_link(node, get_irn_link(block));
1596 set_irn_link(block, node);
1600 /* Links all nodes that have the block field set in the link field of
1601 the block. Adds all blocks and nodes not associated with a block
1602 in a array in irg->link. */
1603 static void collect_nodes() {
1605 for (i = 0; i < get_irp_n_irgs(); i++)
1606 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1607 cg_walk(clear_link, collect_node, NULL);
1610 static void dump_graphs() {
1612 for (i = 0; i < get_irp_n_irgs(); i++) {
1613 current_ir_graph = get_irp_irg(i);
1614 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1618 /* Dump all irgs in interprocedural view to a single file. */
1619 void dump_all_cg_block_graph() {
1621 int rem_view = interprocedural_view;
1622 interprocedural_view = 1;
1623 vcg_open_name ("All_graphs");
1628 if (dump_loop_information_flag)
1629 for (i = 0; i < get_irp_n_irgs(); i++)
1630 dump_loop_info(get_irp_irg(i));
1633 interprocedural_view = rem_view;
1636 /* dump interprocedural block graph with surrounding methods */
1637 void dump_cg_graph(ir_graph * irg) {
1638 pmap * map = pmap_create();
1639 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1643 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1644 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1645 pmap_insert(map2, entry->key, entry->value);
1646 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1647 ir_node ** arr = entry->value;
1649 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1651 xfprintf(F, "graph: { title: \"%I\" label: \"%I\" status:clustered color:white \n",
1652 irg_ident, irg_ident);
1654 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1655 ir_node * node = arr[i];
1656 dump_node(node, map2);
1657 dump_ir_data_edges(node);
1658 if (is_Block(node)) {
1659 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1660 dump_node(node, map2);
1661 dump_ir_block_edge(node);
1662 dump_ir_data_edges(node);
1669 /* Close the vcg information for the irg */
1670 xfprintf(F, "}\n\n");