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