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