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