We now conform to iso-c99
[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", id_to_str(get_entity_ident(ent)), id_to_str(get_entity_ld_ident(ent)));
669   fprintf(F, "\noffset:  %d", get_entity_offset(ent));
670   if (is_method_type(get_entity_type(ent))) {
671     if (get_entity_irg(ent))   /* can be null */
672       { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
673     else
674       { fprintf (F, "\nirg = NULL"); }
675   }
676   fprintf(F, "\"\n}\n");
677 }
678
679 /* dumps a type or entity and it's edges. */
680 static void
681 dump_type_info (type_or_ent *tore, void *env) {
682   int i = 0;  /* to shutup gcc */
683
684   /* dump this type or entity */
685
686   switch (get_kind(tore)) {
687   case k_entity:
688     {
689       entity *ent = (entity *)tore;
690       ir_node *value;
691       /* The node */
692       dump_entity_node(ent);
693       /* The Edges */
694       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
695       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
696                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
697       PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
698       if(is_class_type(get_entity_owner(ent))) {
699         for(i = 0; i < get_entity_n_overwrites(ent); i++){
700           PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
701         }
702       }
703       /* attached subgraphs */
704       if (const_entities && (get_entity_variability(ent) != uninitialized)) {
705         if (is_atomic_entity(ent)) {
706           value = get_atomic_ent_value(ent);
707           if (value) {
708             PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
709             /*
710             fprintf (F, "edge: { sourcename: \"%p\" targetname: ", GET_ENTID(ent));
711             PRINT_NODEID(value);
712             fprintf(F, " " ENT_VALUE_EDGE_ATTR "\"}\n");
713             */
714             dump_const_expression(value);
715           }
716         }
717         if (is_compound_entity(ent)) {
718           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
719             value = get_compound_ent_value(ent, i);
720             if (value) {
721               PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
722               dump_const_expression(value);
723               PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
724               /*
725                 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
726                 ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
727                 get_compound_ent_value_member(ent, i), i);
728               */
729             }
730           }
731         }
732       }
733     } break;
734   case k_type:
735     {
736       type *tp = (type *)tore;
737       print_type_node(tp);
738       /* and now the edges */
739       switch (get_type_tpop_code(tp)) {
740       case tpo_class:
741         {
742           for (i=0; i < get_class_n_supertypes(tp); i++) {
743             PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
744           }
745
746           for (i=0; i < get_class_n_members(tp); i++) {
747             PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
748           }
749         } break;
750       case tpo_struct:
751         {
752           for (i=0; i < get_struct_n_members(tp); i++) {
753             PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
754           }
755         } break;
756       case tpo_method:
757         {
758           for (i = 0; i < get_method_n_params(tp); i++)
759           {
760                   PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
761           }
762           for (i = 0; i < get_method_n_ress(tp); i++)
763           {
764                   PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
765           }
766         } break;
767       case tpo_union:
768         {
769           for (i = 0; i < get_union_n_members(tp); i++)
770           {
771                   PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
772           }
773         } break;
774       case tpo_array:
775         {
776                   PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
777                   PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
778         } break;
779       case tpo_enumeration:
780         {
781         } break;
782       case tpo_pointer:
783         {
784                   PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
785         } break;
786       case tpo_primitive:
787         {
788         } break;
789       default: break;
790       } /* switch type */
791     }
792     break; /* case k_type */
793   default:
794     {
795       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
796     } break;
797   } /* switch kind_or_entity */
798 }
799
800 /* dumps a class type node and a superclass edge.
801    If env != null dumps entities of classes and overwrites edges. */
802 static void
803 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
804   int i = 0;  /* to shutup gcc */
805
806   /* dump this type or entity */
807   switch (get_kind(tore)) {
808   case k_entity: {
809     entity *ent = (entity *)tore;
810     if (get_entity_owner(ent) == get_glob_type()) break;
811     if ((env) && is_class_type(get_entity_owner(ent))) {
812       /* The node */
813       dump_entity_node(ent);
814       /* The edges */
815       PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
816       for(i = 0; i < get_entity_n_overwrites(ent); i++)
817       {
818       PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
819       }
820     }
821   } break; /* case k_entity */
822   case k_type:
823     {
824       type *tp = (type *)tore;
825       if (tp == get_glob_type()) break;
826       switch (get_type_tpop_code(tp)) {
827         case tpo_class: {
828           print_type_node(tp);
829           /* and now the edges */
830           for (i=0; i < get_class_n_supertypes(tp); i++)
831           {
832                   PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
833           }
834         } break;
835         default: break;
836       } /* switch type */
837     }
838     break; /* case k_type */
839   default:
840     {
841       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
842     } break;
843   } /* switch kind_or_entity */
844 }
845
846 /************************************************************************/
847 /* open and close vcg file                                              */
848 /************************************************************************/
849
850 static void vcg_open (ir_graph *irg, char *suffix) {
851   char *fname;  /* filename to put the vcg information in */
852   const char *cp;
853   ident *id;
854   int len;
855   char label[4];
856   entity *ent;
857
858   /** open file for vcg graph */
859   ent = get_irg_ent(irg);
860   id    = ent->ld_name ? ent->ld_name : ent->name;
861   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
862   len   = id_to_strlen (id);
863   cp    = id_to_str (id);
864   if (dump_file_suffix)
865     fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
866   else
867     fname = malloc (len + 5 + strlen(suffix));
868   strncpy (fname, cp, len);      /* copy the filename */
869   fname[len] = '\0';
870   if (dump_file_suffix) strcat (fname, dump_file_suffix);  /* append file suffix */
871   strcat (fname, suffix);  /* append file suffix */
872   strcat (fname, ".vcg");   /* append the .vcg suffix */
873   F = fopen (fname, "w");   /* open file for writing */
874   if (!F) {
875     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
876   }
877
878   if (edge_label) {
879     strcpy(label, "yes");
880   } else {
881     strcpy (label, "no");
882   }
883
884   /* print header */
885   fprintf (F,
886             "graph: { title: \"ir graph of %s\"\n"
887             "display_edge_labels: %s\n"
888             "layoutalgorithm: mindepth\n"
889             "manhattan_edges: yes\n"
890             "port_sharing: no\n"
891             "orientation: bottom_to_top\n"
892             "classname 1: \"Data\"\n"
893             "classname 2: \"Block\"\n"
894             "classname 3: \"Entity type\""
895             "classname 4: \"Entity owner\""
896             "classname 5: \"Method Param\""
897             "classname 6: \"Method Res\""
898             "classname 7: \"Super\""
899             "classname 8: \"Union\""
900             "classname 9: \"Points-to\""
901             "classname 10: \"Array Element Type\""
902             "classname 11: \"Overwrites\""
903             "classname 12: \"Member\""
904             , cp, label);
905
906   fprintf (F, "\n");            /* a separator */
907 }
908
909 static void vcg_open_name (const char *name) {
910   char *fname;  /* filename to put the vcg information in */
911   int len;
912   char label[4];
913
914   /** open file for vcg graph */
915   len   = strlen(name);
916   fname = malloc (len + 5);
917   if (dump_file_suffix)
918     fname = malloc (len + 5 + strlen(dump_file_suffix));
919   else
920     fname = malloc (len + 5);
921   strcpy (fname, name);    /* copy the filename */
922   if (dump_file_suffix) strcat (fname, dump_file_suffix);
923   strcat (fname, ".vcg");  /* append the .vcg suffix */
924   F = fopen (fname, "w");  /* open file for writing */
925   if (!F) {
926     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
927   }
928
929   if (edge_label) {
930     strcpy(label, "yes");
931   } else {
932     strcpy (label, "no");
933   }
934
935   /* print header */
936   fprintf (F,
937             "graph: { title: \"ir graph of %s\"\n"
938             "display_edge_labels: %s\n"
939             "layoutalgorithm: mindepth\n"
940             "manhattan_edges: yes\n"
941             "port_sharing: no\n"
942             "orientation: bottom_to_top\n"
943             "classname 1: \"Data\"\n"
944             "classname 2: \"Block\"\n"
945             "classname 3: \"Entity type\"\n"
946             "classname 4: \"Entity owner\"\n"
947             "classname 5: \"Method Param\"\n"
948             "classname 6: \"Method Res\"\n"
949             "classname 7: \"Super\"\n"
950             "classname 8: \"Union\"\n"
951             "classname 9: \"Points-to\"\n"
952             "classname 10: \"Array Element Type\"\n"
953             "classname 11: \"Overwrites\"\n"
954             "classname 12: \"Member\"\n"
955             , name, label);
956
957   fprintf (F, "\n");            /* a separator */
958 }
959
960 static void
961 vcg_close (void) {
962   fprintf (F, "}\n");  /* print footer */
963   fclose (F);           /* close vcg file */
964 }
965
966 /************************************************************************/
967 /* routines to dump a graph, blocks as conventional nodes.              */
968 /************************************************************************/
969
970 static int node_floats(ir_node *n) {
971   return ((get_op_pinned(get_irn_op(n)) == floats) &&
972           (get_irg_pinned(current_ir_graph) == floats));
973 }
974
975 static void
976 dump_whole_node (ir_node *n, void* env) {
977   dump_node(n, NULL);
978   if (!node_floats(n)) dump_ir_block_edge(n);
979   dump_ir_data_edges(n);
980 }
981
982 void
983 dump_ir_graph (ir_graph *irg)
984 {
985   ir_graph *rem;
986   rem = current_ir_graph;
987   current_ir_graph = irg;
988
989   vcg_open (irg, "");
990
991   /* walk over the graph */
992   /* dump_whole_node must be called in post visiting predecessors */
993   irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
994
995   /* dump the out edges in a separate walk */
996   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
997     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
998   }
999
1000   vcg_close();
1001
1002   current_ir_graph = rem;
1003 }
1004
1005 /***********************************************************************/
1006 /* the following routines dump the nodes as attached to the blocks.    */
1007 /***********************************************************************/
1008
1009 static void
1010 dump_ir_blocks_nodes (ir_node *n, void *env) {
1011   ir_node *block = (ir_node *)env;
1012
1013   if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1014     dump_node(n, NULL);
1015     dump_ir_data_edges(n);
1016   }
1017   if (get_irn_op(n) == op_Bad)
1018     Bad_dumped = 1;
1019 }
1020
1021 static void
1022 dump_ir_block (ir_node *block, void *env) {
1023   ir_graph *irg = (ir_graph *)env;
1024
1025   if (get_irn_opcode(block) == iro_Block) {
1026
1027     /* This is a block. So dump the vcg information to make a block. */
1028     fprintf(F, "graph: { title: ");
1029         PRINT_NODEID(block);
1030         fprintf(F, "  label: \"");
1031 #ifdef DEBUG_libfirm
1032     fprintf (F, "%ld", get_irn_node_nr(block));
1033 #else
1034     fprintf (F, "%s", get_op_name(get_irn_op(block)));
1035 #endif
1036     if (exc_normal != get_Block_exc (block))
1037       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1038
1039     fprintf(F, "\" status:clustered color:%s \n",
1040              get_Block_matured (block) ? "yellow" : "red");
1041     /* dump the blocks edges */
1042     dump_ir_data_edges(block);
1043
1044     /* dump the nodes that go into the block */
1045     irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1046
1047     /* Close the vcg information for the block */
1048     fprintf(F, "}\n\n");
1049     dump_const_node_local(block, NULL);
1050   }
1051 }
1052
1053
1054 static void
1055 dump_blockless_nodes (ir_node *n, void *env) {
1056   if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1057     dump_node(n, NULL);
1058     dump_ir_data_edges(n);
1059     dump_ir_block_edge(n);
1060     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1061     return;
1062   }
1063   if (node_floats(n)) {
1064     dump_node(n, NULL);
1065     dump_ir_data_edges(n);
1066     if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1067   }
1068 }
1069
1070 static void dump_ir_block_graph_2  (ir_graph *irg)
1071 {
1072   Bad_dumped = 0;
1073   /* walk over the blocks in the graph */
1074   irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1075
1076   /* dump all nodes that are not in a Block */
1077   irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1078
1079   /* dump the Bad node */
1080   if (!Bad_dumped)
1081     dump_node(get_irg_bad(irg), NULL);
1082 }
1083
1084 void
1085 dump_ir_block_graph (ir_graph *irg)
1086 {
1087   ir_graph *rem;
1088   rem = current_ir_graph;
1089   current_ir_graph = irg;
1090
1091   vcg_open (irg, "");
1092
1093   dump_ir_block_graph_2 (irg);
1094
1095   if (dump_loop_information_flag) dump_loop_info(irg);
1096
1097   vcg_close();
1098   current_ir_graph = rem;
1099 }
1100
1101
1102 /***********************************************************************/
1103 /* the following routines dump a control flow graph                    */
1104 /***********************************************************************/
1105
1106
1107 static void
1108 dump_block_to_cfg (ir_node *block, void *env) {
1109   int i;
1110   ir_node *pred;
1111
1112   if (get_irn_opcode(block) == iro_Block) {
1113     /* This is a block. Dump a node for the block. */
1114     fprintf (F, "node: {title:"); PRINT_NODEID(block);
1115     fprintf (F, " label: \"%s ", get_op_name(get_irn_op(block)));
1116 #ifdef DEBUG_libfirm
1117     fprintf (F, "%ld", get_irn_node_nr(block));
1118 #else
1119     fprintf (F, "%p", (void*) block);
1120 #endif
1121
1122     if (exc_normal != get_Block_exc (block))
1123       fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1124
1125     fprintf (F, "\" ");
1126     if (dump_dominator_information_flag)
1127       fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1128     fprintf (F, "}\n");
1129     /* Dump the edges */
1130     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1131       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1132         pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1133         fprintf (F, "edge: { sourcename: ");
1134         PRINT_NODEID(block);
1135         fprintf (F, " targetname: ");
1136         PRINT_NODEID(pred);
1137         fprintf (F, " }\n");
1138       }
1139
1140     /* Dump dominator edge */
1141     if (dump_dominator_information_flag && get_Block_idom(block)) {
1142       pred = get_Block_idom(block);
1143       fprintf (F, "edge: { sourcename: ");
1144       PRINT_NODEID(block);
1145       fprintf (F, " targetname: ");
1146       PRINT_NODEID(pred);
1147       fprintf (F, " " DOMINATOR_EDGE_ATTR "}\n");
1148     }
1149   }
1150 }
1151
1152 void
1153 dump_cfg (ir_graph *irg)
1154 {
1155   ir_graph *rem = current_ir_graph;
1156   int ddif = dump_dominator_information_flag;
1157   current_ir_graph = irg;
1158   vcg_open (irg, "-cfg");
1159
1160   if (get_irg_dom_state(irg) != dom_consistent)
1161     dump_dominator_information_flag = 0;
1162
1163   /* walk over the blocks in the graph */
1164   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1165   dump_node (get_irg_bad(irg), NULL);
1166
1167   dump_dominator_information_flag = ddif;
1168   vcg_close();
1169   current_ir_graph = rem;
1170 }
1171
1172
1173 /***********************************************************************/
1174 /* the following routine dumps all type information reachable from an  */
1175 /* irg                                                                 */
1176 /***********************************************************************/
1177
1178
1179 void
1180 dump_type_graph (ir_graph *irg)
1181 {
1182   ir_graph *rem;
1183   rem = current_ir_graph;
1184   current_ir_graph = irg;
1185
1186   vcg_open (irg, "-type");
1187
1188   /* walk over the blocks in the graph */
1189   type_walk_irg(irg, dump_type_info, NULL, NULL);
1190   /* The walker for the const code can be called several times for the
1191      same (sub) experssion.  So that no nodes are dumped several times
1192      we decrease the visited flag of the corresponding graph after each
1193      walk.  So now increase it finally. */
1194   inc_irg_visited(get_const_code_irg());
1195
1196   vcg_close();
1197   current_ir_graph = rem;
1198 }
1199
1200 /***********************************************************************/
1201 /* the following routine dumps all type information                    */
1202 /***********************************************************************/
1203
1204
1205 void
1206 dump_all_types (void)
1207 {
1208   vcg_open_name ("All_types");
1209   type_walk(dump_type_info, NULL, NULL);
1210   inc_irg_visited(get_const_code_irg());
1211   vcg_close();
1212 }
1213
1214 void
1215 dump_class_hierarchy (bool entities)
1216 {
1217   vcg_open_name ("class_hierarchy");
1218   if (entities)
1219     type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1220   else
1221     type_walk(dump_class_hierarchy_node, NULL, NULL);
1222   vcg_close();
1223 }
1224
1225 /***********************************************************************/
1226 /* dumps a graph with type information                                 */
1227 /***********************************************************************/
1228
1229
1230 void
1231 dump_ir_graph_w_types (ir_graph *irg)
1232 {
1233   ir_graph *rem;
1234   rem = current_ir_graph;
1235   current_ir_graph = irg;
1236
1237   vcg_open (irg, "-all");
1238
1239   /* dump common ir graph */
1240   irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1241   /* dump type info */
1242   type_walk_irg(irg, dump_type_info, NULL, NULL);
1243   inc_irg_visited(get_const_code_irg());
1244   /* dump edges from graph to type info */
1245   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1246
1247   vcg_close();
1248   current_ir_graph = rem;
1249 }
1250
1251 void
1252 dump_ir_block_graph_w_types (ir_graph *irg)
1253 {
1254   ir_graph *rem;
1255   rem = current_ir_graph;
1256   current_ir_graph = irg;
1257
1258   vcg_open (irg, "-all");
1259
1260   /* dump common blocked ir graph */
1261   dump_ir_block_graph_2(irg);
1262   /* dump type info */
1263   type_walk_irg(irg, dump_type_info, NULL, NULL);
1264   inc_irg_visited(get_const_code_irg());
1265   /* dump edges from graph to type info */
1266   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1267
1268   vcg_close();
1269   current_ir_graph = rem;
1270 }
1271
1272 /***********************************************************************/
1273 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
1274 /*  dump_ir_graph                                                      */
1275 /*  dump_ir_block_graph                                                */
1276 /*  dump_cfg                                                           */
1277 /*  dump_type_graph                                                    */
1278 /*  dump_ir_graph_w_types                                              */
1279 /***********************************************************************/
1280 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1281   int i;
1282   for (i=0; i < get_irp_n_irgs(); i++) {
1283     dump_graph(get_irp_irg(i));
1284   }
1285 }
1286
1287
1288 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
1289    abort with a segmentation fault. */
1290 void turn_off_edge_labels(void) {
1291   edge_label = 0;
1292 }
1293
1294
1295 void dump_consts_local(bool b) {
1296   dump_const_local = b;
1297 }
1298
1299 void turn_off_constant_entity_values(void) {
1300   const_entities = 0;
1301 }
1302
1303 void dump_keepalive_edges(bool b) {
1304   dump_keepalive = b;
1305 }
1306
1307 bool get_opt_dump_keepalive_edges(void) {
1308   return dump_keepalive;
1309 }
1310
1311 void dump_out_edges(void) {
1312   dump_out_edge_flag = 1;
1313 }
1314
1315 void dump_dominator_information(void) {
1316   dump_dominator_information_flag = 1;
1317 }
1318
1319 void dump_loop_information(void) {
1320   dump_loop_information_flag = 1;
1321 }
1322
1323 void dont_dump_loop_information(void) {
1324   dump_loop_information_flag = 0;
1325 }
1326
1327 static void clear_link(ir_node * node, void * env) {
1328   set_irn_link(node, NULL);
1329 }
1330
1331 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1332   if (is_Block(node)
1333       || node_floats(node)
1334       || get_irn_op(node) == op_Bad
1335       || get_irn_op(node) == op_Unknown) {
1336     pmap_entry * entry = pmap_find(map, current_ir_graph);
1337     if (entry)
1338     {
1339       ir_node ** arr;
1340       arr = entry->value;
1341       ARR_APP1(ir_node *, arr , node);
1342     } else {
1343       ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1344       arr[0] = node;
1345       pmap_insert(map, current_ir_graph, arr);
1346     }
1347   } else {
1348     ir_node * block = get_nodes_Block(node);
1349     set_irn_link(node, get_irn_link(block));
1350     set_irn_link(block, node);
1351   }
1352 }
1353
1354
1355 static void dump_cg_ir_block(ir_node * block, void * env) {
1356   ir_node *node;
1357   pmap *irgmap = (pmap *)env;
1358   assert(is_Block(block));
1359   fprintf(F, "graph: { title: ");
1360   PRINT_NODEID(block);
1361   fprintf(F, "  label: \"");
1362   fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1363 #ifdef DEBUG_libfirm
1364   fprintf (F, "%ld", get_irn_node_nr(block));
1365 #else
1366   fprintf (F, "%p", (void*) block);
1367 #endif
1368   if (exc_normal != get_Block_exc(block)) {
1369     fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1370   }
1371
1372   fprintf(F, "\" status:clustered color:%s \n",
1373            get_Block_matured(block) ? "yellow" : "red");
1374
1375   /* dump the blocks edges */
1376   dump_ir_data_edges(block);
1377
1378   /* dump the nodes that go into the block */
1379   for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1380     dump_node(node, irgmap);
1381     dump_ir_data_edges(node);
1382   }
1383
1384   /* Close the vcg information for the block */
1385   fprintf(F, "}\n\n");
1386 }
1387
1388 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1389   int i;
1390
1391   fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1392            (void*) irg, id_to_str(get_entity_ident(get_irg_ent(irg))));
1393
1394   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1395     ir_node * node = arr[i];
1396     if (is_Block(node)) {
1397       /* Dumps the block and all the nodes in the block , which are to
1398          be found in Block->link. */
1399       dump_cg_ir_block(node, irgmap);
1400     } else {
1401       /* Nodes that are not in a Block. */
1402       dump_node(node, NULL);
1403       dump_ir_data_edges(node);
1404     }
1405   }
1406   /* Close the vcg information for the irg */
1407   fprintf(F, "}\n\n");
1408 }
1409
1410 /* dump interprocedural graph with surrounding methods */
1411 void dump_cg_block_graph(ir_graph * irg) {
1412   pmap * map = pmap_create();
1413   pmap * map2 = pmap_create();
1414   pmap_entry * entry;
1415
1416   vcg_open(irg, "");
1417
1418   irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1419   for (entry = pmap_first(map); entry; entry = pmap_next(map))
1420     pmap_insert(map2, entry->key, entry->value);
1421   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1422     d_cg_block_graph(entry->key, entry->value, map2);
1423     DEL_ARR_F(entry->value);
1424   }
1425
1426   pmap_destroy(map);
1427   pmap_destroy(map2);
1428
1429   if (dump_loop_information_flag) dump_loop_info(irg);
1430   vcg_close();
1431 }
1432
1433 static void collect_node(ir_node * node, void *env) {
1434   if (is_Block(node)
1435       || node_floats(node)
1436       || get_irn_op(node) == op_Bad
1437       || get_irn_op(node) == op_Unknown) {
1438     ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1439     ARR_APP1(ir_node *, arr, node);
1440     set_irg_link(current_ir_graph, arr);    /* arr is an l-value, APP_ARR might change it! */
1441   } else {
1442     ir_node * block = get_nodes_Block(node);
1443     set_irn_link(node, get_irn_link(block));
1444     set_irn_link(block, node);
1445   }
1446 }
1447
1448 /* Links all nodes that have the block field set in the link field of
1449    the block.  Adds all blocks and nodes not associated with a block
1450    in a array in irg->link. */
1451 static void collect_nodes(void) {
1452   int i;
1453   for (i = 0; i < get_irp_n_irgs(); i++)
1454     set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1455   cg_walk(clear_link, collect_node, NULL);
1456 }
1457
1458 static void dump_graphs(void) {
1459   int i;
1460   for (i = 0; i < get_irp_n_irgs(); i++) {
1461     current_ir_graph = get_irp_irg(i);
1462     d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1463   }
1464 }
1465
1466 /* Dump all irgs in interprocedural view to a single file. */
1467 void dump_all_cg_block_graph(void) {
1468   int i;
1469   int rem_view = interprocedural_view;
1470   interprocedural_view = 1;
1471   vcg_open_name ("All_graphs");
1472
1473   collect_nodes();
1474   dump_graphs();
1475
1476   if (dump_loop_information_flag)
1477     for (i = 0; i < get_irp_n_irgs(); i++)
1478       dump_loop_info(get_irp_irg(i));
1479
1480   vcg_close();
1481   interprocedural_view = rem_view;
1482 }
1483
1484 /* dump interprocedural block graph with surrounding methods */
1485 void dump_cg_graph(ir_graph * irg) {
1486   pmap * map = pmap_create();
1487   pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1488   pmap_entry * entry;
1489   vcg_open(irg, "");
1490
1491   irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1492   for (entry = pmap_first(map); entry; entry = pmap_next(map))
1493     pmap_insert(map2, entry->key, entry->value);
1494   for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1495     ir_node ** arr = entry->value;
1496     int i;
1497     ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1498
1499     fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1500              id_to_str(irg_ident), id_to_str(irg_ident));
1501
1502     for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1503       ir_node * node = arr[i];
1504       dump_node(node, map2);
1505       dump_ir_data_edges(node);
1506       if (is_Block(node)) {
1507         for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1508           dump_node(node, map2);
1509           dump_ir_block_edge(node);
1510           dump_ir_data_edges(node);
1511         }
1512       }
1513     }
1514
1515     DEL_ARR_F(arr);
1516
1517     /* Close the vcg information for the irg */
1518     fprintf(F, "}\n\n");
1519   }
1520
1521   pmap_destroy(map);
1522   pmap_destroy(map2);
1523
1524   vcg_close();
1525 }