some fixes for xml dumper / still buggy.
[libfirm] / ir / ir / irdump.c
1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
2 * All rights reserved.
3 *
4 * Authors: Martin Trapp, Christian Schaefer
5 *
6 * irdump.h: dumping of an intermediate representation graph
7 */
8
9 /* $Id$ */
10
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 # include <string.h>
16 # include <stdlib.h>
17
18 # include "irnode_t.h"
19 # include "irgraph_t.h"
20 # include "entity_t.h"
21 # include "irop_t.h"
22 # include "firm_common_t.h"
23
24 # include "irdump.h"
25
26 # include "irgwalk.h"
27 # include "typewalk.h"
28 # include "irprog.h"
29 # include "tv_t.h"
30 # include "type_or_entity.h"
31 # include "irouts.h"
32 # include "irdom.h"
33 # include "irloop.h"
34
35 # include "panic.h"
36 # include "array.h"
37 # include "pmap.h"
38
39 # include "exc.h"
40
41
42 /* Attributes of nodes */
43 #define PRINT_DEFAULT_NODE_ATTR
44 #define DEFAULT_NODE_ATTR " "
45 #define DEFAULT_TYPE_ATTRIBUTE " "
46
47 /* Attributes of edges between Firm nodes */
48 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
49 #define CF_EDGE_ATTR    "color: red"
50 #define MEM_EDGE_ATTR   "color: blue"
51 #define DOMINATOR_EDGE_ATTR "color: red"
52
53 #define BACK_EDGE_ATTR "linestyle: dashed "
54
55 /* Attributes of edges between Firm nodes and type/entity nodes */
56 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
57
58 /* Attributes of edges in type/entity graphs. */
59 #define TYPE_METH_NODE_ATTR  "color: lightyellow"
60 #define TYPE_CLASS_NODE_ATTR "color: green"
61 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
62 #define ENTITY_NODE_ATTR     "color: yellow"
63 #define ENT_TYPE_EDGE_ATTR   "class: 3 label: \"type\" color: red"
64 #define ENT_OWN_EDGE_ATTR    "class: 4 label: \"owner\" color: black"
65 #define METH_PAR_EDGE_ATTR   "class: 5 label: \"param %d\" color: green"
66 #define METH_RES_EDGE_ATTR   "class: 6 label: \"res %d\" color: green"
67 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
68 #define UNION_EDGE_ATTR      "class: 8 label: \"component\" color: blue"
69 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
70 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
71 #define ARR_ENT_EDGE_ATTR    "class: 10 label: \"arr ent\" color: green"
72 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
73 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
74 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
75 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
76
77
78 #if DEBUG_libfirm && NODEID_AS_LABEL
79 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
80 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
81 #define PRINT_ENTID(X)  fprintf(F, "e%ld", get_entity_nr(X))
82 #define PRINT_IRGID(X)  fprintf(F, "g%ld", get_irg_graph_nr(X))
83 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
84
85 #else
86 #define PRINT_NODEID(X) fprintf(F, "n%p", (void*) X)
87 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *) X)
88 #define PRINT_ENTID(X)  fprintf(F, "e%p", (void*) X)
89 #define PRINT_IRGID(X)  fprintf(F, "g%p",(void*) X)
90 #define PRINT_CONSTID(X,Y) fprintf(F, "\"%p%p\"", (void*) X, (void*) Y)
91 #endif
92
93 #define PRINT_TYPE_TYPE_EDGE(S,T,...){fprintf (F, "edge: { sourcename: "); PRINT_TYPEID(S); fprintf (F, " targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
94 #define PRINT_TYPE_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: "); PRINT_TYPEID(S); fprintf (F, " targetname: \""); PRINT_ENTID(T); fprintf(F, "\"");  fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
95 #define PRINT_ENT_ENT_EDGE(S,T,...)  {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S);  fprintf (F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
96 #define PRINT_ENT_TYPE_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S);  fprintf (F, "\" targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
97 #define PRINT_NODE_TYPE_EDGE(S,T,...){fprintf (F, "edge: { sourcename: \""); PRINT_NODEID(S); fprintf (F, "\" targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
98 #define PRINT_NODE_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_NODEID(S); fprintf (F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
99 #define PRINT_ENT_NODE_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: \""); PRINT_ENTID(S);  fprintf (F, "\" targetname: \""); PRINT_NODEID(T); fprintf(F, "\""); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
100
101
102 /* A suffix to manipulate the file name. */
103 char *dump_file_suffix = NULL;
104
105 /* file to dump to */
106 static FILE *F;
107
108 /* A compiler option to turn off edge labels */
109 int edge_label = 1;
110 /* A compiler option to turn off dumping values of constant entities */
111 int const_entities = 1;
112 /* A compiler option to dump the keep alive edges */
113 int dump_keepalive = 0;
114 /* Compiler options to dump analysis information in dump_ir_graph */
115 int dump_out_edge_flag = 0;
116 int dump_dominator_information_flag = 0;
117 int dump_loop_information_flag = 0;
118 int dump_const_local = 0;
119
120 INLINE bool get_opt_dump_const_local(void) {
121   if (!dump_out_edge_flag && !dump_loop_information_flag)
122     return dump_const_local;
123   else
124     return false;
125 }
126
127 /* A global variable to record output of the Bad node. */
128 static int Bad_dumped;
129
130 static void dump_ir_blocks_nodes (ir_node *n, void *env);
131 static void dump_whole_node(ir_node *n, void* env);
132
133 /*******************************************************************/
134 /* routines to dump information about a single node                */
135 /*******************************************************************/
136
137
138
139 static INLINE void
140 dump_node_opcode (ir_node *n)
141 {
142   char buf[1024];
143   int res;
144
145   /* Const */
146   if (get_irn_opcode(n) == iro_Const) {    res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
147     assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
148     fprintf(F, buf);
149
150   /* SymConst */
151   } else if (get_irn_opcode(n) == iro_SymConst) {
152     if (get_SymConst_kind(n) == linkage_ptr_info) {
153       /* don't use get_SymConst_ptr_info as it mangles the name. */
154       fprintf (F, "SymC %s", id_to_str(get_SymConst_ptrinfo(n)));
155     } else {
156       assert(get_kind(get_SymConst_type(n)) == k_type);
157       assert(get_type_ident(get_SymConst_type(n)));
158       fprintf (F, "SymC %s ", id_to_str(get_type_ident(get_SymConst_type(n))));
159       if (get_SymConst_kind(n) == type_tag)
160         fprintf (F, "tag");
161       else
162         fprintf (F, "size");
163     }
164
165   /* Filter */
166   } else if (get_irn_opcode(n) == iro_Filter && !interprocedural_view) {
167     fprintf(F, "Proj'");
168
169   /* all others */
170   } else {
171     fprintf (F, "%s", id_to_str(get_irn_opident(n)));
172   }
173 }
174
175 static INLINE void
176 dump_node_mode (ir_node *n)
177 {
178   switch (get_irn_opcode(n)) {
179   case iro_Phi:
180   case iro_Const:
181   case iro_Id:
182   case iro_Proj:
183   case iro_Filter:
184   case iro_Conv:
185   case iro_Tuple:
186   case iro_Add:
187   case iro_Sub:
188   case iro_Mul:
189   case iro_And:
190   case iro_Or:
191   case iro_Eor:
192   case iro_Shl:
193   case iro_Shr:
194   case iro_Abs:
195   case iro_Cmp:
196     fprintf (F, "%s", id_to_str(get_mode_ident(get_irn_mode(n))));
197     break;
198   default:
199     ;
200   }
201 }
202
203 static INLINE void
204 dump_node_nodeattr (ir_node *n)
205 {
206   switch (get_irn_opcode(n)) {
207   case iro_Start:
208     if (false && interprocedural_view) {
209       fprintf (F, "%s", id_to_str(get_entity_ident(get_irg_ent(current_ir_graph))));
210     }
211     break;
212   case iro_Proj:
213     if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
214       fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
215     } else {
216       fprintf (F, "%ld", get_Proj_proj(n));
217     }
218     break;
219   case iro_Filter:
220     fprintf (F, "%ld", get_Filter_proj(n));
221     break;
222   case iro_Sel: {
223     assert(get_kind(get_Sel_entity(n)) == k_entity);
224     fprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
225     } break;
226   default:
227     ;
228   } /* end switch */
229 }
230
231 static INLINE void
232 dump_node_vcgattr (ir_node *n)
233 {
234   switch (get_irn_opcode(n)) {
235   case iro_Start:
236   case iro_EndReg:
237     /* fall through */
238   case iro_EndExcept:
239     /* fall through */
240   case iro_End:
241     fprintf (F, "color: blue");
242     break;
243   case iro_Block:
244     fprintf (F, "color: lightyellow");
245     break;
246   case iro_Phi:
247     fprintf (F, "color: green");
248     break;
249   case iro_Const:
250   case iro_Proj:
251   case iro_Filter:
252   case iro_Tuple:
253     fprintf (F, "color: yellow");
254     break;
255   default:
256     PRINT_DEFAULT_NODE_ATTR;
257   }
258 }
259
260 static INLINE void
261 dump_node_info (ir_node *n) {
262   fprintf (F, " info1: \"visited: %ld\n\"", get_irn_visited(n));
263 }
264
265 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
266   ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
267
268   if (irgmap &&
269       ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
270     ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
271     if (is_ip_cfop(pred)) {
272       ir_graph *irg = get_ip_cfop_irg(pred);
273       if (pmap_find(irgmap, irg) == NULL) return true;
274     }
275   }
276
277   return false;
278 }
279
280
281 static INLINE
282 bool is_constlike_node(ir_node *n) {
283   ir_op *op = get_irn_op(n);
284   return (op == op_Const || op == op_Bad || op == op_SymConst);
285 }
286
287
288 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
289   int i;
290   if (!get_opt_dump_const_local()) return;
291   /* Use visited flag to avoid outputting nodes twice.
292      initialize it first. */
293   for (i = 0; i < get_irn_arity(n); i++) {
294     ir_node *con = get_irn_n(n, i);
295     if (is_constlike_node(con)) {
296       if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
297       set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
298     }
299   }
300   for (i = 0; i < get_irn_arity(n); i++) {
301     ir_node *con = get_irn_n(n, i);
302     if (is_constlike_node(con) && irn_not_visited(con)) {
303       if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
304       mark_irn_visited(con);
305       /* Generate a new name for the node by appending the names of
306          n and const. */
307       fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
308       fprintf(F, " label: \"");
309       dump_node_opcode(con);
310       dump_node_mode (con);
311       fprintf (F, " ");
312       dump_node_nodeattr(con);
313 #ifdef DEBUG_libfirm
314       fprintf (F, " %ld", get_irn_node_nr(con));
315 #endif
316       fprintf (F, "\" ");
317       dump_node_vcgattr(con);
318       dump_node_info(con);
319       fprintf (F, "}\n");
320     }
321   }
322 }
323
324 static void
325 dump_node (ir_node *n, pmap * map) {
326   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
327
328   /* dump this node */
329   fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
330
331   dump_node_opcode(n);
332   dump_node_mode (n);
333   fprintf (F, " ");
334   dump_node_nodeattr(n);
335 #ifdef DEBUG_libfirm
336   fprintf (F, " %ld", get_irn_node_nr(n));
337 #endif
338   fprintf (F, "\" ");
339   dump_node_vcgattr(n);
340   dump_node_info(n);
341   fprintf (F, "}\n");
342   dump_const_node_local(n, map);
343 }
344
345 /* dump the edge to the block this node belongs to */
346 static void
347 dump_ir_block_edge(ir_node *n)  {
348   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
349   if (is_no_Block(n)) {
350     fprintf (F, "edge: { sourcename: \"");
351     PRINT_NODEID(n);
352     fprintf (F, "\" targetname: \"");
353     PRINT_NODEID(get_nodes_Block(n));
354     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
355   }
356 }
357
358 static void print_edge_vcgattr(ir_node *from, int to) {
359   assert(from);
360
361   if (is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR);
362
363   switch (get_irn_opcode(from)) {
364   case iro_Block:
365     fprintf (F, CF_EDGE_ATTR);
366     break;
367   case iro_Start:   break;
368   case iro_End:
369     if (to >= 0) {
370       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
371         fprintf (F, CF_EDGE_ATTR);
372       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
373         fprintf (F, MEM_EDGE_ATTR);
374     }
375     break;
376   case iro_EndReg: break;
377   case iro_EndExcept: break;
378   case iro_Jmp:     break;
379   case iro_Break:   break;
380   case iro_Cond:    break;
381   case iro_Return:
382   case iro_Raise:
383     if (to == 0) fprintf (F, MEM_EDGE_ATTR);
384     break;
385   case iro_Const:   break;
386   case iro_SymConst:break;
387   case iro_Sel:
388   case iro_Call:
389     if (to == 0) fprintf (F, MEM_EDGE_ATTR);
390     break;
391   case iro_CallBegin: break;
392   case iro_Add:     break;
393   case iro_Sub:     break;
394   case iro_Minus:   break;
395   case iro_Mul:     break;
396   case iro_Quot:
397   case iro_DivMod:
398   case iro_Div:
399   case iro_Mod:
400     if (to == 0) fprintf (F, MEM_EDGE_ATTR);
401     break;
402   case iro_Abs:    break;
403   case iro_And:    break;
404   case iro_Or:     break;
405   case iro_Eor:    break;
406   case iro_Shl:    break;
407   case iro_Shr:    break;
408   case iro_Shrs:   break;
409   case iro_Rot:    break;
410   case iro_Cmp:    break;
411   case iro_Conv:   break;
412   case iro_Phi:
413     if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
414     break;
415   case iro_Load:
416   case iro_Store:
417   case iro_Alloc:
418   case iro_Free:
419     if (to == 0) fprintf (F, MEM_EDGE_ATTR);
420     break;
421   case iro_Sync:
422     fprintf (F, MEM_EDGE_ATTR);
423     break;
424   case iro_Tuple:  break;
425   case iro_Proj:
426   case iro_Filter:
427     switch (get_irn_modecode(from)) {
428     case irm_X:
429       fprintf (F, CF_EDGE_ATTR);
430       break;
431     case irm_M:
432       fprintf (F, MEM_EDGE_ATTR);
433       break;
434     default: break;
435     }
436     break;
437   case iro_Bad:    break;
438   case iro_Unknown: break;
439   case iro_Id:     break;
440   default:
441     ;
442   }
443 }
444
445 /* dump edges to our inputs */
446 static void
447 dump_ir_data_edges(ir_node *n)  {
448   int i, visited = get_irn_visited(n);
449
450   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
451     return;
452
453   for (i = 0; i < get_irn_arity(n); i++) {
454     ir_node * pred = get_irn_n(n, i);
455     assert(pred);
456     if ((interprocedural_view && get_irn_visited(pred) < visited))
457       continue; /* pred not dumped */
458     if (is_backedge(n, i))
459       fprintf (F, "backedge: {sourcename: ");
460     else
461       fprintf (F, "edge: {sourcename: \"");
462     PRINT_NODEID(n);
463     fprintf (F, " \" targetname: ");
464     if ((get_opt_dump_const_local()) && is_constlike_node(pred))
465     {
466       PRINT_CONSTID(n,pred);
467     }
468     else
469       {fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
470     }
471     fprintf (F, " label: \"%d\" ", i);
472     print_edge_vcgattr(n, i);
473     fprintf (F, "}\n");
474   }
475 }
476
477 /* dump out edges */
478 static void
479 dump_out_edge (ir_node *n, void* env) {
480   int i;
481   for (i = 0; i < get_irn_n_outs(n); i++) {
482     assert(get_irn_out(n, i));
483     fprintf (F, "edge: {sourcename: \"");
484     PRINT_NODEID(n);
485     fprintf (F, "\" targetname: \"");
486     PRINT_NODEID(get_irn_out(n, i));
487     fprintf (F, "\" color: red linestyle: dashed");
488     fprintf (F, "}\n");
489   }
490 }
491
492 static INLINE void
493 dump_loop_node_edge (ir_loop *loop, int i) {
494   assert(loop);
495   fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
496   PRINT_NODEID(get_loop_node(loop, i));
497   fprintf (F, "\" color: green");
498   fprintf (F, "}\n");
499 }
500
501 static
502 void dump_loops (ir_loop *loop) {
503   int i;
504   /* dump this loop node */
505   fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
506             (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
507   /* dump edges to nodes in loop -- only if it is a real loop */
508   if (get_loop_depth(loop) != 0) {
509     for (i = 0; i < get_loop_n_nodes(loop); i++) {
510       dump_loop_node_edge(loop, i);
511     }
512   }
513   for (i = 0; i < get_loop_n_sons(loop); i++) {
514     dump_loops(get_loop_son(loop, i));
515   }
516 }
517
518 static INLINE
519 void dump_loop_info(ir_graph *irg) {
520   ir_graph *rem = current_ir_graph;
521   current_ir_graph = irg;
522
523   if (get_irg_loop(irg))
524     dump_loops(get_irg_loop(irg));
525
526   current_ir_graph = rem;
527 }
528
529
530 /* dumps the edges between nodes and their type or entity attributes. */
531 static void dump_node2type_edges (ir_node *n, void *env)
532 {
533   assert(n);
534
535   switch (get_irn_opcode(n)) {
536   case iro_Const :
537     /* @@@ some consts have an entity */
538     break;
539   case iro_SymConst:
540     if (   (get_SymConst_kind(n) == type_tag)
541            || (get_SymConst_kind(n) == size))
542     {
543             PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
544     }
545     break;
546   case iro_Sel: {
547             PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
548     } break;
549   case iro_Call: {
550             PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
551     } break;
552   case iro_Alloc: {
553             PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
554     } break;
555   case iro_Free: {
556             PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
557     } break;
558   default:
559     break;
560   }
561 }
562
563
564 /* @@@@ Does not work as someone kills the visited flag. */
565 static void dump_const_expression(ir_node *value) {
566   ir_graph *rem = current_ir_graph;
567   int rem_dump_const_local = dump_const_local;
568   dump_const_local = 0;
569   current_ir_graph = get_const_code_irg();
570   irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
571   /* Decrease visited flag so that we walk with the same flag for the next
572      expresssion.  This guarantees that we don't dump the same node twice,
573      as for const expressions cse is performed to save memory. */
574   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
575   current_ir_graph = rem;
576   dump_const_local = rem_dump_const_local;
577 }
578
579
580 static void print_type_info(type *tp) {
581   if (get_type_state(tp) == layout_undefined) {
582     fprintf(F, "state: layout_undefined\n");
583   } else {
584     fprintf(F, "state: layout_fixed,\n");
585   }
586   if (get_type_mode(tp))
587     fprintf(F, "mode: %s,\n", id_to_str(get_mode_ident(get_type_mode(tp))));
588   fprintf(F, "size: %dB,\n", get_type_size(tp));
589 }
590
591
592 static void print_typespecific_info(type *tp) {
593   switch (get_type_tpop_code(tp)) {
594   case tpo_class:
595     {
596       if(existent == get_class_peculiarity(tp))
597         fprintf (F, " " TYPE_CLASS_NODE_ATTR);
598       else
599         fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
600     } break;
601   case tpo_struct:
602     {
603       fprintf (F, " " TYPE_METH_NODE_ATTR);
604     } break;
605   case tpo_method:
606     {
607     } break;
608   case tpo_union:
609     {
610     } break;
611   case tpo_array:
612     {
613     } break;
614   case tpo_enumeration:
615     {
616     } break;
617   case tpo_pointer:
618     {
619     } break;
620   case tpo_primitive:
621     {
622     } break;
623   default: break;
624   } /* switch type */
625 }
626
627 static void print_type_node(type *tp) {
628   fprintf (F, "node: {title: ");
629   PRINT_TYPEID(tp);
630   fprintf (F, " label: \"%s %s\"", id_to_str(get_type_tpop_nameid(tp)), id_to_str(get_type_ident(tp)));
631   fprintf (F, " info1: \"");
632   print_type_info(tp);
633   fprintf (F, "\"");
634   print_typespecific_info(tp);
635   fprintf (F, "}\n");
636 }
637
638 void dump_entity_node(entity *ent) {
639   fprintf (F, "node: {title: \"");
640   PRINT_ENTID(ent); fprintf(F, "\"");
641   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
642   fprintf (F, "label: ");
643   fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , id_to_str(get_entity_ident(ent)));
644   fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
645   fprintf (F, "\nallocation:  ");
646   switch (get_entity_allocation(ent)) {
647     case dynamic_allocated:   fprintf (F, "dynamic allocated");   break;
648     case automatic_allocated: fprintf (F, "automatic allocated"); break;
649     case static_allocated:    fprintf (F, "static allocated");    break;
650     case parameter_allocated: fprintf (F, "parameter allocated"); break;
651   }
652   fprintf (F, "\nvisibility:  ");
653   switch (get_entity_visibility(ent)) {
654     case local:              fprintf (F, "local");             break;
655     case external_visible:   fprintf (F, "external visible");  break;
656     case external_allocated: fprintf (F, "external allocated"); break;
657   }
658   fprintf (F, "\nvariability: ");
659   switch (get_entity_variability(ent)) {
660     case uninitialized: fprintf (F, "uninitialized");break;
661     case initialized:   fprintf (F, "initialized");  break;
662     case part_constant: fprintf (F, "part_constant");break;
663     case constant:      fprintf (F, "constant");     break;
664   }
665   fprintf (F, "\nvolatility:  ");
666   switch (get_entity_volatility(ent)) {
667     case non_volatile: fprintf (F, "non_volatile"); break;
668     case is_volatile:  fprintf (F, "is_volatile");  break;
669   }
670   fprintf (F, "\npeculiarity: ");
671   switch (get_entity_peculiarity(ent)) {
672     case description: fprintf (F, "description"); break;
673     case inherited:   fprintf (F, "inherited");   break;
674     case existent:    fprintf (F, "existent");    break;
675   }
676   fprintf(F, "\nname:    %s\nld_name: %s",
677           id_to_str(get_entity_ident(ent)),
678           id_to_str(get_entity_ld_ident(ent)));
679   fprintf(F, "\noffset:  %d", get_entity_offset(ent));
680   if (is_method_type(get_entity_type(ent))) {
681     if (get_entity_irg(ent))   /* can be null */
682       { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
683     else
684       { fprintf (F, "\nirg = NULL"); }
685   }
686   fprintf(F, "\"\n}\n");
687 }
688
689 /* dumps a type or entity and it's edges. */
690 static void
691 dump_type_info (type_or_ent *tore, void *env) {
692   int i = 0;  /* to shutup gcc */
693
694   /* dump this type or entity */
695
696   switch (get_kind(tore)) {
697   case k_entity:
698     {
699       entity *ent = (entity *)tore;
700       ir_node *value;
701       /* The node */
702       dump_entity_node(ent);
703       /* The Edges */
704       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
705       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
706                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
707       PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
708       if(is_class_type(get_entity_owner(ent))) {
709         for(i = 0; i < get_entity_n_overwrites(ent); i++){
710           PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
711         }
712       }
713       /* attached subgraphs */
714       if (const_entities && (get_entity_variability(ent) != uninitialized)) {
715         if (is_atomic_entity(ent)) {
716           value = get_atomic_ent_value(ent);
717           if (value) {
718             PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
719             /* DDMN(value);  $$$ */
720             dump_const_expression(value);
721           }
722         }
723         if (is_compound_entity(ent)) {
724           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
725             value = get_compound_ent_value(ent, i);
726             if (value) {
727               PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
728               dump_const_expression(value);
729               PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
730               /*
731                 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
732                 ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
733                 get_compound_ent_value_member(ent, i), i);
734               */
735             }
736           }
737         }
738       }
739     } break;
740   case k_type:
741     {
742       type *tp = (type *)tore;
743       print_type_node(tp);
744       /* and now the edges */
745       switch (get_type_tpop_code(tp)) {
746       case tpo_class:
747         {
748           for (i=0; i < get_class_n_supertypes(tp); i++) {
749             PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
750           }
751
752           for (i=0; i < get_class_n_members(tp); i++) {
753             PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
754           }
755         } break;
756       case tpo_struct:
757         {
758           for (i=0; i < get_struct_n_members(tp); i++) {
759             PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
760           }
761         } break;
762       case tpo_method:
763         {
764           for (i = 0; i < get_method_n_params(tp); i++)
765           {
766                   PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
767           }
768           for (i = 0; i < get_method_n_ress(tp); i++)
769           {
770                   PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
771           }
772         } break;
773       case tpo_union:
774         {
775           for (i = 0; i < get_union_n_members(tp); i++)
776           {
777                   PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
778           }
779         } break;
780       case tpo_array:
781         {
782                   PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
783                   PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
784         } break;
785       case tpo_enumeration:
786         {
787         } break;
788       case tpo_pointer:
789         {
790                   PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
791         } break;
792       case tpo_primitive:
793         {
794         } break;
795       default: break;
796       } /* switch type */
797     }
798     break; /* case k_type */
799   default:
800     {
801       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
802     } break;
803   } /* switch kind_or_entity */
804 }
805
806 /* dumps a class type node and a superclass edge.
807    If env != null dumps entities of classes and overwrites edges. */
808 static void
809 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
810   int i = 0;  /* to shutup gcc */
811
812   /* dump this type or entity */
813   switch (get_kind(tore)) {
814   case k_entity: {
815     entity *ent = (entity *)tore;
816     if (get_entity_owner(ent) == get_glob_type()) break;
817     if ((env) && is_class_type(get_entity_owner(ent))) {
818       /* The node */
819       dump_entity_node(ent);
820       /* The edges */
821       PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
822       for(i = 0; i < get_entity_n_overwrites(ent); i++)
823       {
824       PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
825       }
826     }
827   } break; /* case k_entity */
828   case k_type:
829     {
830       type *tp = (type *)tore;
831       if (tp == get_glob_type()) break;
832       switch (get_type_tpop_code(tp)) {
833         case tpo_class: {
834           print_type_node(tp);
835           /* and now the edges */
836           for (i=0; i < get_class_n_supertypes(tp); i++)
837           {
838                   PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
839           }
840         } break;
841         default: break;
842       } /* switch type */
843     }
844     break; /* case k_type */
845   default:
846     {
847       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
848     } break;
849   } /* switch kind_or_entity */
850 }
851
852 /************************************************************************/
853 /* open and close vcg file                                              */
854 /************************************************************************/
855
856 static void vcg_open (ir_graph *irg, char *suffix) {
857   char *fname;  /* filename to put the vcg information in */
858   const char *cp;
859   ident *id;
860   int len;
861   char label[4];
862   entity *ent;
863
864   /** open file for vcg graph */
865   ent = get_irg_ent(irg);
866   id    = ent->ld_name ? ent->ld_name : ent->name;
867   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
868   len   = id_to_strlen (id);
869   cp    = id_to_str (id);
870   if (dump_file_suffix)
871     fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
872   else
873     fname = malloc (len + 5 + strlen(suffix));
874   strncpy (fname, cp, len);      /* copy the filename */
875   fname[len] = '\0';
876   if (dump_file_suffix) strcat (fname, dump_file_suffix);  /* append file suffix */
877   strcat (fname, suffix);  /* append file suffix */
878   strcat (fname, ".vcg");   /* append the .vcg suffix */
879   F = fopen (fname, "w");   /* open file for writing */
880   if (!F) {
881     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
882   }
883
884   if (edge_label) {
885     strcpy(label, "yes");
886   } else {
887     strcpy (label, "no");
888   }
889
890   /* print header */
891   fprintf (F,
892             "graph: { title: \"ir graph of %s\"\n"
893             "display_edge_labels: %s\n"
894             "layoutalgorithm: mindepth\n"
895             "manhattan_edges: yes\n"
896             "port_sharing: no\n"
897             "orientation: bottom_to_top\n"
898             "classname 1: \"Data\"\n"
899             "classname 2: \"Block\"\n"
900             "classname 3: \"Entity type\""
901             "classname 4: \"Entity owner\""
902             "classname 5: \"Method Param\""
903             "classname 6: \"Method Res\""
904             "classname 7: \"Super\""
905             "classname 8: \"Union\""
906             "classname 9: \"Points-to\""
907             "classname 10: \"Array Element Type\""
908             "classname 11: \"Overwrites\""
909             "classname 12: \"Member\""
910             , cp, label);
911
912   fprintf (F, "\n");            /* a separator */
913 }
914
915 static void vcg_open_name (const char *name) {
916   char *fname;  /* filename to put the vcg information in */
917   int len;
918   char label[4];
919
920   /** open file for vcg graph */
921   len   = strlen(name);
922   fname = malloc (len + 5);
923   if (dump_file_suffix)
924     fname = malloc (len + 5 + strlen(dump_file_suffix));
925   else
926     fname = malloc (len + 5);
927   strcpy (fname, name);    /* copy the filename */
928   if (dump_file_suffix) strcat (fname, dump_file_suffix);
929   strcat (fname, ".vcg");  /* append the .vcg suffix */
930   F = fopen (fname, "w");  /* open file for writing */
931   if (!F) {
932     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
933   }
934
935   if (edge_label) {
936     strcpy(label, "yes");
937   } else {
938     strcpy (label, "no");
939   }
940
941   /* print header */
942   fprintf (F,
943             "graph: { title: \"ir graph of %s\"\n"
944             "display_edge_labels: %s\n"
945             "layoutalgorithm: mindepth\n"
946             "manhattan_edges: yes\n"
947             "port_sharing: no\n"
948             "orientation: bottom_to_top\n"
949             "classname 1: \"Data\"\n"
950             "classname 2: \"Block\"\n"
951             "classname 3: \"Entity type\"\n"
952             "classname 4: \"Entity owner\"\n"
953             "classname 5: \"Method Param\"\n"
954             "classname 6: \"Method Res\"\n"
955             "classname 7: \"Super\"\n"
956             "classname 8: \"Union\"\n"
957             "classname 9: \"Points-to\"\n"
958             "classname 10: \"Array Element Type\"\n"
959             "classname 11: \"Overwrites\"\n"
960             "classname 12: \"Member\"\n"
961             , name, label);
962
963   fprintf (F, "\n");            /* a separator */
964 }
965
966 static void
967 vcg_close (void) {
968   fprintf (F, "}\n");  /* print footer */
969   fclose (F);           /* close vcg file */
970 }
971
972 /************************************************************************/
973 /* routines to dump a graph, blocks as conventional nodes.              */
974 /************************************************************************/
975
976 static int node_floats(ir_node *n) {
977   return ((get_op_pinned(get_irn_op(n)) == floats) &&
978           (get_irg_pinned(current_ir_graph) == floats));
979 }
980
981 static void
982 dump_whole_node (ir_node *n, void* env) {
983   dump_node(n, NULL);
984   if (!node_floats(n)) dump_ir_block_edge(n);
985   dump_ir_data_edges(n);
986 }
987
988 void
989 dump_ir_graph (ir_graph *irg)
990 {
991   ir_graph *rem;
992   rem = current_ir_graph;
993   current_ir_graph = irg;
994
995   vcg_open (irg, "");
996
997   /* walk over the graph */
998   /* dump_whole_node must be called in post visiting predecessors */
999   irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1000
1001   /* dump the out edges in a separate walk */
1002   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1003     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1004   }
1005
1006   vcg_close();
1007
1008   current_ir_graph = rem;
1009 }
1010
1011 /***********************************************************************/
1012 /* the following routines dump the nodes as attached to the blocks.    */
1013 /***********************************************************************/
1014
1015 static void
1016 dump_ir_blocks_nodes (ir_node *n, void *env) {
1017   ir_node *block = (ir_node *)env;
1018
1019   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1020     dump_node(n, NULL);
1021     dump_ir_data_edges(n);
1022   }
1023   if (get_irn_op(n) == op_Bad)
1024     Bad_dumped = 1;
1025 }
1026
1027 static void
1028 dump_ir_block (ir_node *block, void *env) {
1029   ir_graph *irg = (ir_graph *)env;
1030
1031   if (get_irn_opcode(block) == iro_Block) {
1032
1033     /* This is a block. So dump the vcg information to make a block. */
1034     fprintf(F, "graph: { title: \"");
1035         PRINT_NODEID(block);
1036         fprintf(F, "\" label: \"");
1037 #ifdef DEBUG_libfirm
1038     fprintf (F, "%ld", get_irn_node_nr(block));
1039 #else
1040     fprintf (F, "%s", get_op_name(get_irn_op(block)));
1041 #endif
1042     if (exc_normal != get_Block_exc (block))
1043       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1044
1045     fprintf(F, "\" status:clustered color:%s \n",
1046              get_Block_matured (block) ? "yellow" : "red");
1047     /* dump the blocks edges */
1048     dump_ir_data_edges(block);
1049
1050     /* dump the nodes that go into the block */
1051     irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1052
1053     /* Close the vcg information for the block */
1054     fprintf(F, "}\n\n");
1055     dump_const_node_local(block, NULL);
1056   }
1057 }
1058
1059
1060 static void
1061 dump_blockless_nodes (ir_node *n, void *env) {
1062   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1063     dump_node(n, NULL);
1064     dump_ir_data_edges(n);
1065     dump_ir_block_edge(n);
1066     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1067     return;
1068   }
1069   if (node_floats(n)) {
1070     dump_node(n, NULL);
1071     dump_ir_data_edges(n);
1072     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1073   }
1074 }
1075
1076 static void dump_ir_block_graph_2  (ir_graph *irg)
1077 {
1078   Bad_dumped = 0;
1079   /* walk over the blocks in the graph */
1080   irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1081
1082   /* dump all nodes that are not in a Block */
1083   irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1084
1085   /* dump the Bad node */
1086   if (!Bad_dumped)
1087     dump_node(get_irg_bad(irg), NULL);
1088 }
1089
1090 void
1091 dump_ir_block_graph (ir_graph *irg)
1092 {
1093   ir_graph *rem;
1094   rem = current_ir_graph;
1095   current_ir_graph = irg;
1096
1097   vcg_open (irg, "");
1098
1099   dump_ir_block_graph_2 (irg);
1100
1101   if (dump_loop_information_flag) dump_loop_info(irg);
1102
1103   vcg_close();
1104   current_ir_graph = rem;
1105 }
1106
1107
1108 /***********************************************************************/
1109 /* the following routines dump a control flow graph                    */
1110 /***********************************************************************/
1111
1112
1113 static void
1114 dump_block_to_cfg (ir_node *block, void *env) {
1115   int i;
1116   ir_node *pred;
1117
1118   if (get_irn_opcode(block) == iro_Block) {
1119     /* This is a block. Dump a node for the block. */
1120     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1121     fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1122 #ifdef DEBUG_libfirm
1123     fprintf (F, "%ld", get_irn_node_nr(block));
1124 #else
1125     fprintf (F, "%p", (void*) block);
1126 #endif
1127
1128     if (exc_normal != get_Block_exc (block))
1129       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1130
1131     fprintf (F, "\" ");
1132     if (dump_dominator_information_flag)
1133       fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1134     fprintf (F, "}\n");
1135     /* Dump the edges */
1136     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1137       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1138         pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1139         fprintf (F, "edge: { sourcename: \"");
1140         PRINT_NODEID(block);
1141         fprintf (F, "\" targetname: \"");
1142         PRINT_NODEID(pred);
1143         fprintf (F, "\"}\n");
1144       }
1145
1146     /* Dump dominator edge */
1147     if (dump_dominator_information_flag && get_Block_idom(block)) {
1148       pred = get_Block_idom(block);
1149       fprintf (F, "edge: { sourcename: \"");
1150       PRINT_NODEID(block);
1151       fprintf (F, "\" targetname: \"");
1152       PRINT_NODEID(pred);
1153       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1154     }
1155   }
1156 }
1157
1158 void
1159 dump_cfg (ir_graph *irg)
1160 {
1161   ir_graph *rem = current_ir_graph;
1162   int ddif = dump_dominator_information_flag;
1163   current_ir_graph = irg;
1164   vcg_open (irg, "-cfg");
1165
1166   if (get_irg_dom_state(irg) != dom_consistent)
1167     dump_dominator_information_flag = 0;
1168
1169   /* walk over the blocks in the graph */
1170   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1171   dump_node (get_irg_bad(irg), NULL);
1172
1173   dump_dominator_information_flag = ddif;
1174   vcg_close();
1175   current_ir_graph = rem;
1176 }
1177
1178
1179 /***********************************************************************/
1180 /* the following routine dumps all type information reachable from an  */
1181 /* irg                                                                 */
1182 /***********************************************************************/
1183
1184
1185 void
1186 dump_type_graph (ir_graph *irg)
1187 {
1188   ir_graph *rem;
1189   rem = current_ir_graph;
1190   current_ir_graph = irg;
1191
1192   vcg_open (irg, "-type");
1193
1194   /* walk over the blocks in the graph */
1195   type_walk_irg(irg, dump_type_info, NULL, NULL);
1196   /* The walker for the const code can be called several times for the
1197      same (sub) experssion.  So that no nodes are dumped several times
1198      we decrease the visited flag of the corresponding graph after each
1199      walk.  So now increase it finally. */
1200   inc_irg_visited(get_const_code_irg());
1201
1202   vcg_close();
1203   current_ir_graph = rem;
1204 }
1205
1206 /***********************************************************************/
1207 /* the following routine dumps all type information                    */
1208 /***********************************************************************/
1209
1210
1211 void
1212 dump_all_types (void)
1213 {
1214   vcg_open_name ("All_types");
1215   type_walk(dump_type_info, NULL, NULL);
1216   inc_irg_visited(get_const_code_irg());
1217   vcg_close();
1218 }
1219
1220 void
1221 dump_class_hierarchy (bool entities)
1222 {
1223   vcg_open_name ("class_hierarchy");
1224   if (entities)
1225     type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1226   else
1227     type_walk(dump_class_hierarchy_node, NULL, NULL);
1228   vcg_close();
1229 }
1230
1231 /***********************************************************************/
1232 /* dumps a graph with type information                                 */
1233 /***********************************************************************/
1234
1235
1236 void
1237 dump_ir_graph_w_types (ir_graph *irg)
1238 {
1239   ir_graph *rem;
1240   rem = current_ir_graph;
1241   current_ir_graph = irg;
1242
1243   vcg_open (irg, "-all");
1244
1245   /* dump common ir graph */
1246   irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1247   /* dump type info */
1248   type_walk_irg(irg, dump_type_info, NULL, NULL);
1249   inc_irg_visited(get_const_code_irg());
1250   /* dump edges from graph to type info */
1251   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1252
1253   vcg_close();
1254   current_ir_graph = rem;
1255 }
1256
1257 void
1258 dump_ir_block_graph_w_types (ir_graph *irg)
1259 {
1260   ir_graph *rem;
1261   rem = current_ir_graph;
1262   current_ir_graph = irg;
1263
1264   vcg_open (irg, "-all");
1265
1266   /* dump common blocked ir graph */
1267   dump_ir_block_graph_2(irg);
1268   /* dump type info */
1269   type_walk_irg(irg, dump_type_info, NULL, NULL);
1270   inc_irg_visited(get_const_code_irg());
1271   /* dump edges from graph to type info */
1272   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1273
1274   vcg_close();
1275   current_ir_graph = rem;
1276 }
1277
1278 /***********************************************************************/
1279 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1280 /*  dump_ir_graph                                                      */
1281 /*  dump_ir_block_graph                                                */
1282 /*  dump_cfg                                                           */
1283 /*  dump_type_graph                                                    */
1284 /*  dump_ir_graph_w_types                                              */
1285 /***********************************************************************/
1286 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1287   int i;
1288   for (i=0; i < get_irp_n_irgs(); i++) {
1289     dump_graph(get_irp_irg(i));
1290   }
1291 }
1292
1293
1294 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1295    abort with a segmentation fault. */
1296 void turn_off_edge_labels(void) {
1297   edge_label = 0;
1298 }
1299
1300
1301 void dump_consts_local(bool b) {
1302   dump_const_local = b;
1303 }
1304
1305 void turn_off_constant_entity_values(void) {
1306   const_entities = 0;
1307 }
1308
1309 void dump_keepalive_edges(bool b) {
1310   dump_keepalive = b;
1311 }
1312
1313 bool get_opt_dump_keepalive_edges(void) {
1314   return dump_keepalive;
1315 }
1316
1317 void dump_out_edges(void) {
1318   dump_out_edge_flag = 1;
1319 }
1320
1321 void dump_dominator_information(void) {
1322   dump_dominator_information_flag = 1;
1323 }
1324
1325 void dump_loop_information(void) {
1326   dump_loop_information_flag = 1;
1327 }
1328
1329 void dont_dump_loop_information(void) {
1330   dump_loop_information_flag = 0;
1331 }
1332
1333 static void clear_link(ir_node * node, void * env) {
1334   set_irn_link(node, NULL);
1335 }
1336
1337 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1338   assert(node); assert(map);
1339   if (is_Block(node)
1340       || node_floats(node)
1341       || get_irn_op(node) == op_Bad
1342       || get_irn_op(node) == op_Unknown) {
1343     pmap_entry * entry = pmap_find(map, current_ir_graph);
1344     if (entry)
1345     {
1346       ir_node ** arr;
1347       arr = entry->value;
1348       assert(arr);
1349       ARR_APP1(ir_node *, arr , node);
1350     } else {
1351       ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1352       assert(arr);
1353       arr[0] = node;
1354       pmap_insert(map, current_ir_graph, arr);
1355     }
1356   } else {
1357     ir_node * block = get_nodes_Block(node);
1358     set_irn_link(node, get_irn_link(block));
1359     set_irn_link(block, node);
1360   }
1361 }
1362
1363
1364 static void dump_cg_ir_block(ir_node * block, void * env) {
1365   ir_node *node;
1366   pmap *irgmap = (pmap *)env;
1367   assert(is_Block(block));
1368   fprintf(F, "graph: { title: \"");
1369   PRINT_NODEID(block);
1370   fprintf(F, "\"  label: \"");
1371   fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1372 #ifdef DEBUG_libfirm
1373   fprintf (F, "%ld", get_irn_node_nr(block));
1374 #else
1375   fprintf (F, "%p", (void*) block);
1376 #endif
1377   if (exc_normal != get_Block_exc(block)) {
1378     fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1379   }
1380
1381   fprintf(F, "\" status:clustered color:%s \n",
1382            get_Block_matured(block) ? "yellow" : "red");
1383
1384   /* dump the blocks edges */
1385   dump_ir_data_edges(block);
1386
1387   /* dump the nodes that go into the block */
1388   for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1389     dump_node(node, irgmap);
1390     dump_ir_data_edges(node);
1391   }
1392
1393   /* Close the vcg information for the block */
1394   fprintf(F, "}\n\n");
1395 }
1396
1397 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1398   int i;
1399
1400   fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1401            (void*) irg, id_to_str(get_entity_ident(get_irg_ent(irg))));
1402
1403   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1404     ir_node * node = arr[i];
1405     if (is_Block(node)) {
1406       /* Dumps the block and all the nodes in the block , which are to
1407          be found in Block->link. */
1408       dump_cg_ir_block(node, irgmap);
1409     } else {
1410       /* Nodes that are not in a Block. */
1411       dump_node(node, NULL);
1412       dump_ir_data_edges(node);
1413     }
1414   }
1415   /* Close the vcg information for the irg */
1416   fprintf(F, "}\n\n");
1417 }
1418
1419 /* dump interprocedural graph with surrounding methods */
1420 void dump_cg_block_graph(ir_graph * irg) {
1421   pmap * map = pmap_create();
1422   pmap * map2 = pmap_create();
1423   pmap_entry * entry;
1424
1425   vcg_open(irg, "");
1426
1427   irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1428   for (entry = pmap_first(map); entry; entry = pmap_next(map))
1429     pmap_insert(map2, entry->key, entry->value);
1430   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1431     d_cg_block_graph(entry->key, entry->value, map2);
1432     DEL_ARR_F(entry->value);
1433   }
1434
1435   pmap_destroy(map);
1436   pmap_destroy(map2);
1437
1438   if (dump_loop_information_flag) dump_loop_info(irg);
1439   vcg_close();
1440 }
1441
1442 static void collect_node(ir_node * node, void *env) {
1443   if (is_Block(node)
1444       || node_floats(node)
1445       || get_irn_op(node) == op_Bad
1446       || get_irn_op(node) == op_Unknown) {
1447     ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1448     ARR_APP1(ir_node *, arr, node);
1449     set_irg_link(current_ir_graph, arr);    /* arr is an l-value, APP_ARR might change it! */
1450   } else {
1451     ir_node * block = get_nodes_Block(node);
1452     set_irn_link(node, get_irn_link(block));
1453     set_irn_link(block, node);
1454   }
1455 }
1456
1457 /* Links all nodes that have the block field set in the link field of
1458    the block.  Adds all blocks and nodes not associated with a block
1459    in a array in irg->link. */
1460 static void collect_nodes(void) {
1461   int i;
1462   for (i = 0; i < get_irp_n_irgs(); i++)
1463     set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1464   cg_walk(clear_link, collect_node, NULL);
1465 }
1466
1467 static void dump_graphs(void) {
1468   int i;
1469   for (i = 0; i < get_irp_n_irgs(); i++) {
1470     current_ir_graph = get_irp_irg(i);
1471     d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1472   }
1473 }
1474
1475 /* Dump all irgs in interprocedural view to a single file. */
1476 void dump_all_cg_block_graph(void) {
1477   int i;
1478   int rem_view = interprocedural_view;
1479   interprocedural_view = 1;
1480   vcg_open_name ("All_graphs");
1481
1482   collect_nodes();
1483   dump_graphs();
1484
1485   if (dump_loop_information_flag)
1486     for (i = 0; i < get_irp_n_irgs(); i++)
1487       dump_loop_info(get_irp_irg(i));
1488
1489   vcg_close();
1490   interprocedural_view = rem_view;
1491 }
1492
1493 /* dump interprocedural block graph with surrounding methods */
1494 void dump_cg_graph(ir_graph * irg) {
1495   pmap * map = pmap_create();
1496   pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1497   pmap_entry * entry;
1498   vcg_open(irg, "");
1499
1500   irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1501   for (entry = pmap_first(map); entry; entry = pmap_next(map))
1502     pmap_insert(map2, entry->key, entry->value);
1503   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1504     ir_node ** arr = entry->value;
1505     int i;
1506     ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1507
1508     fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1509              id_to_str(irg_ident), id_to_str(irg_ident));
1510
1511     for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1512       ir_node * node = arr[i];
1513       dump_node(node, map2);
1514       dump_ir_data_edges(node);
1515       if (is_Block(node)) {
1516         for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1517           dump_node(node, map2);
1518           dump_ir_block_edge(node);
1519           dump_ir_data_edges(node);
1520         }
1521       }
1522     }
1523
1524     DEL_ARR_F(arr);
1525
1526     /* Close the vcg information for the irg */
1527     fprintf(F, "}\n\n");
1528   }
1529
1530   pmap_destroy(map);
1531   pmap_destroy(map2);
1532
1533   vcg_close();
1534 }