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