added dumper for callgraph
[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 "irprog_t.h"
25 #include "entity_t.h"
26 #include "irop_t.h"
27 #include "firm_common_t.h"
28
29 #include "irdump.h"
30
31 #include "irgwalk.h"
32 #include "typewalk.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 #include "callgraph.h"
39
40 #include "irvrfy.h"
41
42 #include "panic.h"
43 #include "array.h"
44 #include "pmap.h"
45 #include "eset.h"
46
47 #if DO_HEAPANALYSIS
48 void dump_chi_term(FILE *FL, ir_node *n);
49 void dump_state(FILE *FL, ir_node *n);
50 int  get_opt_dump_abstvals(void);
51 typedef unsigned long SeqNo;
52 SeqNo get_Block_seqno(ir_node *n);
53 #endif
54
55 /* Attributes of nodes */
56 #define PRINT_DEFAULT_NODE_ATTR
57 #define DEFAULT_NODE_ATTR " "
58 #define DEFAULT_TYPE_ATTRIBUTE " "
59 #define DEFAULT_ENUM_ITEM_ATTRIBUTE " "
60
61 /* Attributes of edges between Firm nodes */
62 #define INTRA_DATA_EDGE_ATTR "class:1  priority:50"
63 #define INTER_DATA_EDGE_ATTR "class:16 priority:10"
64 #define BLOCK_EDGE_ATTR      "class:2  priority:50 linestyle:dotted"
65 #define CF_EDGE_ATTR         "class:13 priority:60 color:red"
66 #define INTRA_MEM_EDGE_ATTR  "class:14 priority:50 color:blue"
67 #define INTER_MEM_EDGE_ATTR  "class:17 priority:10 color:blue"
68 #define DOMINATOR_EDGE_ATTR  "class:15 color:red"
69
70 #define BACK_EDGE_ATTR "linestyle:dashed "
71
72 /* Attributes of edges between Firm nodes and type/entity nodes */
73 #define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"
74
75 /* Attributes of edges in type/entity graphs. */
76 #define TYPE_METH_NODE_ATTR      "color: lightyellow"
77 #define TYPE_CLASS_NODE_ATTR     "color: green"
78 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
79 #define ENTITY_NODE_ATTR         "color: yellow"
80 #define ENT_TYPE_EDGE_ATTR       "class: 3 label: \"type\" color: red"
81 #define ENT_OWN_EDGE_ATTR        "class: 4 label: \"owner\" color: black"
82 #define METH_PAR_EDGE_ATTR       "class: 5 label: \"param %d\" color: green"
83 #define METH_RES_EDGE_ATTR       "class: 6 label: \"res %d\" color: green"
84 #define TYPE_SUPER_EDGE_ATTR     "class: 7 label: \"supertype\" color: red"
85 #define UNION_EDGE_ATTR          "class: 8 label: \"component\" color: blue"
86 #define PTR_PTS_TO_EDGE_ATTR     "class: 9 label: \"points to\" color:green"
87 #define ARR_ELT_TYPE_EDGE_ATTR   "class: 10 label: \"arr elt tp\" color:green"
88 #define ARR_ENT_EDGE_ATTR        "class: 10 label: \"arr ent\" color: green"
89 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
90 #define ENT_VALUE_EDGE_ATTR      "label: \"value %d\""
91 #define ENT_CORR_EDGE_ATTR       "label: \"value %d corresponds to \" "
92 #define TYPE_MEMBER_EDGE_ATTR    "class: 12 label: \"member\" color:blue"
93 #define ENUM_ITEM_NODE_ATTR      "color: green"
94 #define CALLGRAPH_EDGE_ATTR      "calls"
95
96 #if DEBUG_libfirm && NODEID_AS_LABEL
97 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
98 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
99 #define PRINT_ENTID(X)  fprintf(F, "e%ld", get_entity_nr(X))
100 #define PRINT_IRGID(X)  fprintf(F, "g%ld", get_irg_graph_nr(X))
101 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
102 #define PRINT_LOOPID(X) fprintf(F, "l%d", get_loop_loop_nr(X))
103 #define PRINT_ITEMID(X,Y)  fprintf(F, "i%ldT%d", get_type_nr(X), (Y))
104
105 #else
106 #define PRINT_NODEID(X) fprintf(F, "n%p", (void *)(X))
107 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *)(X))
108 #define PRINT_ENTID(X)  fprintf(F, "e%p", (void *)(X))
109 #define PRINT_IRGID(X)  fprintf(F, "g%p",(void *)(X))
110 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%pn%p\"", (void*)(X), (void*)(Y))
111 #define PRINT_LOOPID(X) fprintf(F, "l%p", (void *)(X))
112 #define PRINT_ITEMID(X,Y)  fprintf(F, "i%pT%d", (void *) (X), (Y))
113 #endif
114
115
116 int my_special_flag = 0;
117
118 static const char *get_mode_name_ex(ir_mode *mode, int *bad)
119 {
120   if (is_mode(mode))
121     return get_mode_name(mode);
122   *bad |= 1;
123   return "<ERROR>";
124 }
125
126 static const char *get_type_name_ex(type *tp, int *bad)
127 {
128   if (is_type(tp))
129     return get_type_name(tp);
130   *bad |= 1;
131   return "<ERROR>";
132 }
133
134 static void print_type_type_edge(FILE *F, type *S, type *T, const char *fmt, ...)
135 {
136   va_list ap;
137
138   va_start(ap, fmt);
139   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
140   fprintf(F, " targetname: "); PRINT_TYPEID(T);
141   vfprintf(F, fmt, ap);
142   fprintf(F,"}\n");
143   va_end(ap);
144 }
145
146 static void print_type_ent_edge(FILE *F, type *T, entity *E, const char *fmt, ...)
147 {
148   va_list ap;
149
150   va_start(ap, fmt);
151   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(T);
152   fprintf(F, " targetname: \""); PRINT_ENTID(E); fprintf(F, "\"");
153   vfprintf(F, fmt, ap);
154   fprintf(F, "}\n");
155   va_end(ap);
156 }
157
158 static void print_ent_ent_edge(FILE *F, entity *E, entity *T, int backedge, const char *fmt, ...)
159 {
160   va_list ap;
161
162   va_start(ap, fmt);
163   if (backedge)
164     fprintf(F, "backedge: { sourcename: \"");
165    else
166     fprintf(F, "edge: { sourcename: \"");
167   PRINT_ENTID(E);
168   fprintf(F, "\" targetname: \""); PRINT_ENTID(T);  fprintf(F, "\"");
169   vfprintf(F, fmt, ap);
170   fprintf(F, "}\n");
171   va_end(ap);
172 }
173
174 static void print_ent_type_edge(FILE *F, entity *E, type *T, const char *fmt, ...)
175 {
176   va_list ap;
177
178   va_start(ap, fmt);
179   fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
180   fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
181   vfprintf(F, fmt, ap);
182   fprintf(F,"}\n");
183   va_end(ap);
184 }
185
186 static void print_node_type_edge(FILE *F, const ir_node *N, type *T, const char *fmt, ...)
187 {
188   va_list ap;
189
190   va_start(ap, fmt);
191   fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
192   fprintf(F, "\" targetname: "); PRINT_TYPEID(T);
193   vfprintf(F, fmt, ap);
194   fprintf(F,"}\n");
195   va_end(ap);
196 }
197
198 static void print_node_ent_edge(FILE *F, const ir_node *N, entity *E, const char *fmt, ...)
199 {
200   va_list ap;
201
202   va_start(ap, fmt);
203   fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(N);
204   fprintf(F, "\" targetname: \""); PRINT_ENTID(E);
205   fprintf(F, "\"");
206   vfprintf(F, fmt, ap);
207   fprintf(F,"}\n");
208   va_end(ap);
209 }
210
211 static void print_ent_node_edge(FILE *F, entity *E, const ir_node *N, const char *fmt, ...)
212 {
213   va_list ap;
214
215   va_start(ap, fmt);
216   fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(E);
217   fprintf(F, "\" targetname: \""); PRINT_NODEID(N); fprintf(F, "\"");
218   vfprintf(F, fmt, ap);
219   fprintf(F,"}\n");
220   va_end(ap);
221 }
222
223 static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, ...)
224 {
225   va_list ap;
226
227   va_start(ap, fmt);
228   fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(E);
229   fprintf(F, " targetname: \""); PRINT_ITEMID(E, item); fprintf(F, "\" ");
230   vfprintf(F, fmt, ap);
231   fprintf(F,"}\n");
232   va_end(ap);
233 }
234
235 /*******************************************************************/
236 /* global and ahead declarations                                   */
237 /*******************************************************************/
238
239 /* A suffix to manipulate the file name. */
240
241 char *dump_file_filter = "";
242
243 static void dump_whole_node(ir_node *n, void *env);
244 static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
245
246 /*******************************************************************/
247 /* Helper functions.                                                */
248 /*******************************************************************/
249
250 /* Use private link attr to be able to call dumper anywhere without
251    destroying link fields. */
252
253 static pmap *irdump_link_map = NULL;
254
255 static void init_irdump(void) {
256   /* We need a new, empty map. */
257   if (irdump_link_map) pmap_destroy(irdump_link_map);
258   irdump_link_map = pmap_create();
259 }
260
261
262 void *ird_get_irn_link(ir_node *n) {
263   void *res = NULL;
264   if (!irdump_link_map) return NULL;
265
266   if (pmap_contains(irdump_link_map, (void *)n))
267     res = pmap_get(irdump_link_map, (void *)n);
268   return res;
269 }
270
271 void ird_set_irn_link(ir_node *n, void *x) {
272   if (!irdump_link_map) init_irdump();
273   pmap_insert(irdump_link_map, (void *)n, x);
274 }
275
276 void *ird_get_irg_link(ir_graph *irg) {
277   void *res = NULL;
278   if (!irdump_link_map) return NULL;
279
280   if (pmap_contains(irdump_link_map, (void *)irg))
281     res = pmap_get(irdump_link_map, (void *)irg);
282   return res;
283 }
284
285 void ird_set_irg_link(ir_graph *irg, void *x) {
286   if (!irdump_link_map) init_irdump();
287   pmap_insert(irdump_link_map, (void *)irg, x);
288 }
289
290 static void clear_link(ir_node * node, void * env) {
291   ird_set_irn_link(node, NULL);
292 }
293
294
295 static int node_floats(ir_node *n) {
296   return ((get_op_pinned(get_irn_op(n)) == op_pin_state_floats) &&
297       (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
298 }
299
300 static const char *get_ent_dump_name(entity *ent) {
301   if (! ent)
302     return "<NULL entity>";
303   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
304   if (ent->ld_name) return get_id_str(ent->ld_name);
305   return get_id_str(ent->name);
306 }
307
308 static const char *get_irg_dump_name(ir_graph *irg) {
309   /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
310   entity *ent = get_irg_entity(irg);
311   return get_ent_dump_name(ent);
312 }
313
314 static void collect_node(ir_node * node, void *env) {
315   if (is_Block(node)
316       || node_floats(node)
317       || get_irn_op(node) == op_Bad
318       || get_irn_op(node) == op_Unknown) {
319     ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
320     if (!arr) arr = NEW_ARR_F(ir_node *, 0);
321     ARR_APP1(ir_node *, arr, node);
322     ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
323   } else {
324     ir_node * block = get_nodes_block(node);
325     ird_set_irn_link(node, ird_get_irn_link(block));
326     ird_set_irn_link(block, node);
327   }
328 }
329
330 /** Construct lists to walk ir block-wise.
331  *
332  * Collects all blocks, nodes not op_pin_state_pinned,
333  * Bad and Unknown into a flexible array in link field of
334  * irg they belong to.  Sets the irg link field to NULL in all
335  * graphs not visited.
336  * Free the list with DEL_ARR_F.  */
337 static ir_node ** construct_block_lists(ir_graph *irg) {
338   int i, rem_view = interprocedural_view;
339   ir_graph *rem = current_ir_graph;
340   current_ir_graph = irg;
341
342   for (i = 0; i < get_irp_n_irgs(); i++)
343     ird_set_irg_link(get_irp_irg(i), NULL);
344
345   irg_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
346
347   /* Collect also EndReg and EndExcept. We do not want to change the walker. */
348   interprocedural_view = 0;
349   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
350   irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
351   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
352   irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
353   interprocedural_view = rem_view;
354
355   current_ir_graph = rem;
356   return ird_get_irg_link(irg);
357 }
358
359 /*******************************************************************/
360 /* flags to steer output                                           */
361 /*******************************************************************/
362
363 /* A compiler option to turn off edge labels */
364 int edge_label = 1;
365 /* A compiler option to turn off dumping values of constant entities */
366 int const_entities = 1;
367 /* A compiler option to dump the keep alive edges */
368 int dump_keepalive = 0;
369 /* Compiler options to dump analysis information in dump_ir_graph */
370 int dump_out_edge_flag = 0;
371 int dump_dominator_information_flag = 0;
372 int dump_loop_information_flag = 0;
373 int dump_backedge_information_flag = 1;
374 int dump_const_local = 0;
375 bool opt_dump_analysed_type_info = 1;
376 bool opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
377
378 char* overrule_nodecolor = NULL;
379
380 INLINE bool get_opt_dump_const_local(void) {
381   if (!dump_out_edge_flag && !dump_loop_information_flag)
382     return dump_const_local;
383   else
384     return false;
385 }
386
387 /* To turn off display of edge labels.  Edge labels offen cause xvcg to
388    abort with a segmentation fault. */
389 void turn_off_edge_labels(void) {
390   edge_label = 0;
391 }
392
393 void dump_consts_local(bool b) {
394   dump_const_local = b;
395 }
396
397 void turn_off_constant_entity_values(void) {
398   const_entities = 0;
399 }
400
401 void dump_keepalive_edges(bool b) {
402   dump_keepalive = b;
403 }
404
405 bool get_opt_dump_keepalive_edges(void) {
406   return dump_keepalive;
407 }
408
409 void dump_out_edges(void) {
410   dump_out_edge_flag = 1;
411 }
412
413 void dump_dominator_information(void) {
414   dump_dominator_information_flag = 1;
415 }
416
417 void dump_loop_information(void) {
418   dump_loop_information_flag = 1;
419 }
420
421 void dont_dump_loop_information(void) {
422   dump_loop_information_flag = 0;
423 }
424
425 void dump_backedge_information(bool b) {
426   dump_backedge_information_flag = b;
427 }
428
429 /* Dump the information of type field specified in ana/irtypeinfo.h.
430  * If the flag is set, the type name is output in [] in the node label,
431  * else it is output as info.
432  */
433 void dump_analysed_type_info(bool b) {
434   opt_dump_analysed_type_info = b;
435 }
436
437 void dump_pointer_values_to_info(bool b) {
438   opt_dump_pointer_values_to_info = b;
439 }
440
441 /*******************************************************************/
442 /* Routines to dump information about a single ir node.            */
443 /*******************************************************************/
444
445 INLINE int
446 dump_node_opcode(FILE *F, ir_node *n)
447 {
448   int bad = 0;
449
450   switch(get_irn_opcode(n)) {
451
452   case iro_Const: {
453     int res;
454     char buf[1024];
455     res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
456     assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
457     fprintf(F, buf);
458   } break;
459
460   case iro_SymConst: {
461     if (get_SymConst_kind(n) == symconst_addr_name) {
462       /* don't use get_SymConst_ptr_info as it mangles the name. */
463       fprintf (F, "SymC %s", get_id_str(get_SymConst_name(n)));
464     } else if (get_SymConst_kind(n) == symconst_addr_ent) {
465       assert(get_SymConst_entity(n));
466       assert(is_entity(get_SymConst_entity(n)));
467       fprintf (F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
468     } else {
469       assert(get_kind(get_SymConst_type(n)) == k_type);
470       assert(get_type_ident(get_SymConst_type(n)));
471       fprintf (F, "SymC %s ", get_type_name_ex(get_SymConst_type(n), &bad));
472       if (get_SymConst_kind(n) == symconst_type_tag)
473         fprintf (F, "tag");
474       else
475         fprintf (F, "size");
476     }
477   } break;
478
479   case iro_Filter: {
480     if (!interprocedural_view) fprintf(F, "Proj'");
481     else                       goto default_case;
482   } break;
483
484   case iro_Proj: {
485     ir_node *pred = get_Proj_pred(n);
486
487     if (get_irn_opcode(pred) == iro_Cond
488         && get_Proj_proj(n) == get_Cond_defaultProj(pred)
489         && get_irn_mode(get_Cond_selector(pred)) != mode_b)
490       fprintf (F, "defProj");
491 /*
492  *   else if (get_irn_opcode(pred) == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start)
493  *     fprintf (F, "Arg");
494  */
495     else
496       goto default_case;
497   } break;
498   case iro_Start:
499   case iro_End:
500   case iro_EndExcept:
501   case iro_EndReg: {
502     if (interprocedural_view) {
503       fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
504       break;
505     } else
506       goto default_case;
507   }
508   case iro_CallBegin: {
509     ir_node *addr = get_CallBegin_ptr(n);
510     entity *ent = NULL;
511     if (get_irn_op(addr) == op_Sel)
512       ent = get_Sel_entity(addr);
513     else if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind(addr) == symconst_addr_ent))
514       ent = get_SymConst_entity(addr);
515     fprintf (F, "%s", get_irn_opname(n));
516     if (ent) fprintf (F, " %s", get_entity_name(ent));
517     break;
518   }
519
520 default_case:
521   default: {
522     fprintf (F, "%s", get_irn_opname(n));
523   }
524
525   }  /* end switch */
526   return bad;
527 }
528
529 static INLINE int
530 dump_node_mode(FILE *F, ir_node *n)
531 {
532   int bad = 0;
533
534   switch (get_irn_opcode(n)) {
535   case iro_Phi:
536   case iro_Const:
537   case iro_Id:
538   case iro_Proj:
539   case iro_Filter:
540   case iro_Conv:
541   case iro_Tuple:
542   case iro_Add:
543   case iro_Sub:
544   case iro_Mul:
545   case iro_And:
546   case iro_Or:
547   case iro_Eor:
548   case iro_Shl:
549   case iro_Shr:
550   case iro_Abs:
551   case iro_Cmp:
552   case iro_Confirm:
553     fprintf(F, "%s", get_mode_name_ex(get_irn_mode(n), &bad));
554     break;
555   default:
556     ;
557   }
558   return bad;
559 }
560
561 static int dump_node_typeinfo(FILE *F, ir_node *n) {
562   int bad = 0;
563
564   if (opt_dump_analysed_type_info) {
565     if (get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_consistent  ||
566         get_irg_typeinfo_state(current_ir_graph) == irg_typeinfo_inconsistent) {
567       type *tp = get_irn_type(n);
568       if (tp != none_type)
569         fprintf(F, " [%s]", get_type_name_ex(tp, &bad));
570       else
571         fprintf(F, " []");
572     }
573   }
574   return bad;
575 }
576
577 static INLINE int
578 dump_node_nodeattr(FILE *F, ir_node *n)
579 {
580   int bad = 0;
581
582   switch (get_irn_opcode(n)) {
583   case iro_Start:
584     if (false && interprocedural_view) {
585       fprintf (F, "%s", get_ent_dump_name(get_irg_entity(current_ir_graph)));
586     }
587     break;
588   case iro_Proj:
589     if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
590       fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
591     } else {
592       fprintf (F, "%ld", get_Proj_proj(n));
593     }
594     break;
595   case iro_Filter:
596     fprintf (F, "%ld", get_Filter_proj(n));
597     break;
598   case iro_Sel: {
599     fprintf (F, "%s", get_ent_dump_name(get_Sel_entity(n)));
600     } break;
601   case iro_Cast: {
602     fprintf (F, "(%s)", get_type_name_ex(get_Cast_type(n), &bad));
603     } break;
604   case iro_Confirm: {
605     fprintf (F, "%s", get_pnc_string(get_Confirm_cmp(n)));
606     } break;
607
608   default:
609     ;
610   } /* end switch */
611
612   return bad;
613 }
614
615 static INLINE void dump_node_vcgattr(FILE *F, ir_node *n, int bad)
616 {
617   if (bad) {
618     fprintf(F, "color: red");
619     return;
620   }
621   switch (get_irn_opcode(n)) {
622   case iro_Start:
623   case iro_EndReg:
624     /* fall through */
625   case iro_EndExcept:
626     /* fall through */
627   case iro_End:
628     fprintf (F, "color: blue");
629     break;
630   case iro_Block:
631     fprintf (F, "color: lightyellow");
632     break;
633   case iro_Phi:
634     fprintf (F, "color: green");
635     break;
636   case iro_Const:
637   case iro_Proj:
638   case iro_Filter:
639   case iro_Tuple:
640     fprintf (F, "color: yellow");
641     break;
642   default:
643     PRINT_DEFAULT_NODE_ATTR;
644   }
645
646   if (overrule_nodecolor) fprintf(F, " color: %s", overrule_nodecolor);
647 }
648
649 static INLINE int dump_node_info(FILE *F, ir_node *n)
650 {
651   int i, bad = 0;
652   char comma;
653   ir_graph *irg;
654
655   fprintf (F, " info1: \"");
656   if (opt_dump_pointer_values_to_info)
657     fprintf (F, "addr:    %p \n", (void *)n);
658   fprintf (F, "mode:    %s\n", get_mode_name(get_irn_mode(n)));
659   fprintf (F, "visited: %ld \n", get_irn_visited(n));
660   irg = get_irn_irg(n);
661   if (irg != get_const_code_irg())
662     fprintf (F, "irg:     %s\n", get_ent_dump_name(get_irg_entity(irg)));
663
664   fprintf(F, "arity: %d", get_irn_arity(n));
665   if ((get_irn_op(n) == op_Block) ||
666       (get_irn_op(n) == op_Phi) ||
667       ((get_irn_op(n) == op_Filter) && interprocedural_view)) {
668     fprintf(F, " backedges:");
669     comma = ' ';
670     for (i = 0; i < get_irn_arity(n); i++)
671       if (is_backedge(n, i)) { fprintf(F, "%c %d", comma, i); comma = ','; }
672   }
673   fprintf(F, "\n");
674
675   /* Loop node   Someone else please tell me what's wrong ...
676   if (get_irn_loop(n)) {
677     ir_loop *loop = get_irn_loop(n);
678     assert(loop);
679     fprintf(F, " in loop %d with depth %d\n",
680         get_loop_loop_nr(loop), get_loop_depth(loop));
681   }
682   */
683
684   /* Source types */
685   switch (get_irn_opcode(n)) {
686   case iro_Start: {
687     type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
688     fprintf(F, "start of method of type %s \n", get_type_name_ex(tp, &bad));
689     for (i = 0; i < get_method_n_params(tp); ++i)
690       fprintf(F, "  param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
691   } break;
692   case iro_Alloc: {
693     fprintf(F, "allocating entity of type %s \n", get_type_name_ex(get_Alloc_type(n), &bad));
694   } break;
695   case iro_Free: {
696     fprintf(F, "freeing entity of type %s \n", get_type_name_ex(get_Free_type(n), &bad));
697   } break;
698   case iro_Sel: {
699     entity *ent = get_Sel_entity(n);
700
701     if (ent) {
702       fprintf(F, "Selecting entity of type %s\n", get_type_name_ex(get_entity_type(ent), &bad));
703       fprintf(F, "  from entity of type %s\n", get_type_name_ex(get_entity_owner(ent), &bad));
704     }
705     else {
706       fprintf(F, "<NULL entity>\n");
707       bad = 1;
708     }
709   } break;
710   case iro_Call: {
711     type *tp = get_Call_type(n);
712     fprintf(F, "calling method of type %s \n", get_type_name_ex(tp, &bad));
713     for (i = 0; i < get_method_n_params(tp); ++i)
714       fprintf(F, "  param %d type: %s \n", i, get_type_name_ex(get_method_param_type(tp, i), &bad));
715     for (i = 0; i < get_method_n_ress(tp); ++i)
716       fprintf(F, "  resul %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
717     if (0 && Call_has_callees(n)) {
718       fprintf(F, "possible callees: \n");
719       for (i = 0; i < get_Call_n_callees(n); i++) {
720         if (!get_Call_callee(n, i)) {
721           fprintf(F, "  %d external method\n", i);
722         } else {
723           fprintf(F, "  %d: %s\n", i, get_ent_dump_name(get_Call_callee(n, i)));
724         }
725       }
726     }
727   } break;
728   case iro_CallBegin: {
729     ir_node *call = get_CallBegin_call(n);
730     if (Call_has_callees(call)) {
731       fprintf(F, "possible callees: \n");
732       for (i = 0; i < get_Call_n_callees(call); i++) {
733     if (!get_Call_callee(call, i)) {
734       fprintf(F, "  %d external method\n", i);
735     } else {
736       fprintf(F, "  %d: %s\n", i, get_ent_dump_name(get_Call_callee(call, i)));
737     }
738       }
739     }
740   } break;
741   case iro_Return: {
742     if (!interprocedural_view) {
743       type *tp = get_entity_type(get_irg_entity(get_irn_irg(n)));
744       fprintf(F, "return in method of type %s \n", get_type_name_ex(tp, &bad));
745       for (i = 0; i < get_method_n_ress(tp); ++i)
746     fprintf(F, "  res %d type: %s \n", i, get_type_name_ex(get_method_res_type(tp, i), &bad));
747     }
748     } break;
749   case iro_Const: {
750     type *tp = get_Const_type(n);
751     assert(tp != none_type);
752     fprintf(F, "Const of type %s \n", get_type_name_ex(get_Const_type(n), &bad));
753   } break;
754   case iro_SymConst: {
755     switch(get_SymConst_kind(n)) {
756     case symconst_addr_name:
757       fprintf(F, "kind addr_name\n");
758       break;
759     case symconst_addr_ent:
760       fprintf(F, "kind addr_ent\n");
761       break;
762     case symconst_type_tag:
763       fprintf(F, "kind type_tag\n");
764       break;
765     case symconst_size:
766       fprintf(F, "kind size\n");
767       break;
768     }
769   } break;
770   case iro_Filter: {
771     int i;
772     if (interprocedural_view) {
773       fprintf(F, "intra predecessor nodes:\n");
774       for (i = 0; i < get_irn_intra_arity(n); i++) {
775     ir_node *pred = get_irn_intra_n(n, i);
776     fprintf(F, "  %s%s %ld\n", get_irn_opname(pred), get_irn_modename(pred), get_irn_node_nr(pred));
777       }
778     } else {
779       fprintf(F, "inter predecessor nodes:\n");
780       for (i = 0; i < get_irn_inter_arity(n); i++) {
781     ir_node *pred = get_irn_inter_n(n, i);
782     fprintf(F, "  %s%s %ld \tin graph %s\n", get_irn_opname(pred), get_irn_modename(pred),
783         get_irn_node_nr(pred), get_ent_dump_name(get_irg_entity(get_irn_irg(pred))));
784       }
785     }
786   } break;
787   default: ;
788   }
789
790   if (get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_consistent  ||
791       get_irg_typeinfo_state(get_irn_irg(n)) == irg_typeinfo_inconsistent  )
792     if (get_irn_type(n) != none_type)
793       fprintf (F, "\nAnalysed type: %s", get_type_name_ex(get_irn_type(n), &bad));
794
795   fprintf (F, "\"");
796
797   return bad;
798 }
799
800
801 static INLINE
802 bool is_constlike_node(ir_node *n) {
803   ir_op *op = get_irn_op(n);
804   return (op == op_Const || op == op_Bad || op == op_SymConst || op == op_Unknown);
805 }
806
807
808 /* outputs the predecessors of n, that are constants, local.  I.e.,
809    generates a copy of the constant predecessors for each node called with. */
810 static void dump_const_node_local(FILE *F, ir_node *n) {
811   int i;
812   if (!get_opt_dump_const_local()) return;
813
814   /* Use visited flag to avoid outputting nodes twice.
815      initialize it first. */
816   for (i = 0; i < get_irn_arity(n); i++) {
817     ir_node *con = get_irn_n(n, i);
818     if (is_constlike_node(con)) {
819       set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
820     }
821   }
822
823   for (i = 0; i < get_irn_arity(n); i++) {
824     ir_node *con = get_irn_n(n, i);
825     if (is_constlike_node(con) && irn_not_visited(con)) {
826       int bad = 0;
827
828       mark_irn_visited(con);
829       /* Generate a new name for the node by appending the names of
830          n and const. */
831       fprintf(F, "node: {title: "); PRINT_CONSTID(n, con);
832       fprintf(F, " label: \"");
833       bad |= dump_node_opcode(F, con);
834       bad |= dump_node_mode(F, con);
835       bad |= dump_node_typeinfo(F, con);
836       fprintf (F, " ");
837       bad |= dump_node_nodeattr(F, con);
838       fprintf(F, " %ld", get_irn_node_nr(con));
839       fprintf(F, "\" ");
840       bad |= dump_node_info(F, con);
841       dump_node_vcgattr(F, con, bad);
842       fprintf(F, "}\n");
843     }
844   }
845 }
846
847 static void INLINE print_node_error(FILE *F, const char *p)
848 {
849   if (! p)
850     return;
851
852   fprintf (F, " info2: \"%s\"", p);
853 }
854
855 static void dump_node(FILE *F, ir_node *n)
856 {
857   int bad = 0;
858   const char *p;
859
860   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
861   /* dump this node */
862   fprintf(F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
863
864   bad = ! irn_vrfy_irg_dump(n, current_ir_graph, &p);
865   bad |= dump_node_opcode(F, n);
866   bad |= dump_node_mode(F, n);
867   bad |= dump_node_typeinfo(F, n);
868   fprintf(F, " ");
869   bad |= dump_node_nodeattr(F, n);
870   fprintf(F, " %ld", get_irn_node_nr(n));
871   fprintf(F, "\" ");
872   bad |= dump_node_info(F, n);
873   print_node_error(F, p);
874   dump_node_vcgattr(F, n, bad);
875   fprintf(F, "}\n");
876   dump_const_node_local(F, n);
877 #if DO_HEAPANALYSIS
878   dump_chi_term(F, n);
879   dump_state(F, n);
880 #endif
881 }
882
883 /* dump the edge to the block this node belongs to */
884 static void
885 dump_ir_block_edge(FILE *F, ir_node *n)  {
886   if (get_opt_dump_const_local() && is_constlike_node(n)) return;
887   if (is_no_Block(n)) {
888     fprintf (F, "edge: { sourcename: \"");
889     PRINT_NODEID(n);
890     fprintf (F, "\" targetname: \"");
891     PRINT_NODEID(get_nodes_block(n));
892     fprintf (F, "\" "   BLOCK_EDGE_ATTR "}\n");
893   }
894 }
895
896 static void
897 print_data_edge_vcgattr(FILE *F, ir_node *from, int to) {
898   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
899     fprintf (F, INTRA_DATA_EDGE_ATTR);
900   else
901     fprintf (F, INTER_DATA_EDGE_ATTR);
902 }
903
904 static void
905 print_mem_edge_vcgattr(FILE *F, ir_node *from, int to) {
906   if (get_nodes_block(from) == get_nodes_block(get_irn_n(from, to)))
907     fprintf (F, INTRA_MEM_EDGE_ATTR);
908   else
909     fprintf (F, INTER_MEM_EDGE_ATTR);
910 }
911
912 static void
913 print_edge_vcgattr(FILE *F, ir_node *from, int to) {
914   assert(from);
915
916   if (dump_backedge_information_flag && is_backedge(from, to))
917     fprintf (F, BACK_EDGE_ATTR);
918
919   switch (get_irn_opcode(from)) {
920   case iro_Block:
921     fprintf (F, CF_EDGE_ATTR);
922     break;
923   case iro_Start:   break;
924   case iro_End:
925     if (to >= 0) {
926       if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
927     fprintf (F, CF_EDGE_ATTR);
928       if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
929     fprintf (F, INTER_MEM_EDGE_ATTR);
930     }
931     break;
932   case iro_EndReg:
933   case iro_EndExcept:
934   case iro_Jmp:
935   case iro_Break:
936   case iro_Cond:
937     print_data_edge_vcgattr(F, from, to);
938     break;
939   case iro_Return:
940   case iro_Raise:
941     if (to == 0)
942       print_mem_edge_vcgattr(F, from, to);
943     else
944       print_data_edge_vcgattr(F, from, to);
945     break;
946   case iro_Const:
947   case iro_SymConst:
948     print_data_edge_vcgattr(F, from, to);
949     break;
950   case iro_Sel:
951   case iro_Call:
952     if (to == 0)
953       print_mem_edge_vcgattr(F, from, to);
954     else
955       print_data_edge_vcgattr(F, from, to);
956     break;
957   case iro_CallBegin:
958   case iro_Add:
959   case iro_Sub:
960   case iro_Minus:
961   case iro_Mul:
962     print_data_edge_vcgattr(F, from, to);
963     break;
964   case iro_Quot:
965   case iro_DivMod:
966   case iro_Div:
967   case iro_Mod:
968     if (to == 0)
969       print_mem_edge_vcgattr(F, from, to);
970     else
971       print_data_edge_vcgattr(F, from, to);
972     break;
973   case iro_Abs:
974   case iro_And:
975   case iro_Or:
976   case iro_Eor:
977   case iro_Shl:
978   case iro_Shr:
979   case iro_Shrs:
980   case iro_Rot:
981   case iro_Cmp:
982   case iro_Conv:
983       print_data_edge_vcgattr(F, from, to);
984     break;
985   case iro_Phi:
986     if (get_irn_modecode(from) == irm_M)
987       fprintf (F, INTER_MEM_EDGE_ATTR);
988     else
989       print_data_edge_vcgattr(F, from, to);
990     break;
991   case iro_Load:
992   case iro_Store:
993   case iro_Alloc:
994   case iro_Free:
995     if (to == 0)
996       print_mem_edge_vcgattr(F, from, to);
997     else
998       print_data_edge_vcgattr(F, from, to);
999     break;
1000   case iro_Sync:
1001     print_mem_edge_vcgattr(F, from, to);
1002     break;
1003   case iro_Tuple:  break;
1004   case iro_Proj:
1005   case iro_Filter:
1006     switch (get_irn_modecode(from)) {
1007     case irm_X:
1008       fprintf (F, CF_EDGE_ATTR);
1009       break;
1010     case irm_M:
1011       fprintf (F, INTER_MEM_EDGE_ATTR);
1012       break;
1013     default:
1014       print_data_edge_vcgattr(F, from, to);
1015       break;
1016     }
1017     break;
1018   case iro_Bad:     break;
1019   case iro_Unknown: break;
1020   case iro_Id:
1021     switch (get_irn_modecode(from)) {
1022     case irm_M:
1023       fprintf (F, INTRA_MEM_EDGE_ATTR);
1024       break;
1025     case irm_X:
1026       fprintf (F, CF_EDGE_ATTR);
1027       break;
1028     default:
1029       print_data_edge_vcgattr(F, from, to);
1030       break;
1031     } break;
1032   default:
1033     ;
1034   }
1035 }
1036
1037 /* dump edges to our inputs */
1038 static void
1039 dump_ir_data_edges(FILE *F, ir_node *n)  {
1040   int i, visited = get_irn_visited(n);
1041
1042   if ((get_irn_op(n) == op_End) && (!dump_keepalive))
1043     return;
1044
1045   for (i = 0; i < get_irn_arity(n); i++) {
1046     ir_node * pred = get_irn_n(n, i);
1047     assert(pred);
1048
1049     if ((interprocedural_view && get_irn_visited(pred) < visited))
1050       continue; /* pred not dumped */
1051
1052     if (dump_backedge_information_flag && is_backedge(n, i))
1053       fprintf (F, "backedge: {sourcename: \"");
1054     else
1055       fprintf (F, "edge: {sourcename: \"");
1056     PRINT_NODEID(n);
1057     fprintf (F, "\" targetname: ");
1058     if ((get_opt_dump_const_local()) && is_constlike_node(pred)) {
1059       PRINT_CONSTID(n, pred);
1060     } else {
1061       fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
1062     }
1063     fprintf (F, " label: \"%d\" ", i);
1064     print_edge_vcgattr(F, n, i);
1065     fprintf (F, "}\n");
1066   }
1067 }
1068
1069 /** Dumps a node and its edges but not the block edge
1070  */
1071 static INLINE void
1072 dump_node_wo_blockedge (ir_node *n, void *env) {
1073   FILE *F = env;
1074   dump_node(F, n);
1075   dump_ir_data_edges(F, n);
1076 }
1077
1078 /** Dumps a node and its edges.
1079  */
1080 static void
1081 dump_whole_node (ir_node *n, void *env) {
1082   FILE *F = env;
1083   dump_node_wo_blockedge(n, env);
1084   if (!node_floats(n)) dump_ir_block_edge(F, n);
1085 }
1086
1087 static void
1088 dump_const_node(ir_node *n, void *env) {
1089   if (is_Block(n)) return;
1090   dump_node_wo_blockedge(n, env);
1091 }
1092
1093 /***********************************************************************/
1094 /* the following routines dump the nodes/irgs bracketed to graphs.     */
1095 /***********************************************************************/
1096
1097 /** Dumps a constant expression as entity initializer, array bound ...
1098  */
1099 static void dump_const_expression(FILE *F, ir_node *value) {
1100   ir_graph *rem = current_ir_graph;
1101   int rem_dump_const_local = dump_const_local;
1102   dump_const_local = 0;
1103   current_ir_graph = get_const_code_irg();
1104   irg_walk(value, dump_const_node, NULL, F);
1105   /* Decrease visited flag so that we walk with the same flag for the next
1106      expresssion.  This guarantees that we don't dump the same node twice,
1107      as for const expressions cse is performed to save memory. */
1108   set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
1109   current_ir_graph = rem;
1110   dump_const_local = rem_dump_const_local;
1111 }
1112
1113 /** Dump a block as graph containing its nodes.
1114  *
1115  *  Expects to find nodes belonging to the block as list in its
1116  *  link field.
1117  *  Dumps the edges of all nodes including itself. */
1118 static void
1119 dump_whole_block(FILE *F, ir_node *block) {
1120   ir_node *node;
1121   assert(is_Block(block));
1122
1123   fprintf(F, "graph: { title: \"");
1124   PRINT_NODEID(block);
1125   fprintf(F, "\"  label: \"");
1126   dump_node_opcode(F, block);
1127   fprintf (F, " %ld", get_irn_node_nr(block));
1128 #if DO_HEAPANALYSIS
1129   if (get_opt_dump_abstvals())
1130     fprintf (F, " seqno: %d", (int)get_Block_seqno(block));
1131 #endif
1132   fprintf(F, "\" status:clustered color:%s \n",
1133        get_Block_matured(block) ? "yellow" : "red");
1134
1135   /* dump the blocks edges */
1136   dump_ir_data_edges(F, block);
1137
1138   /* dump the nodes that go into the block */
1139   for (node = ird_get_irn_link(block); node; node = ird_get_irn_link(node)) {
1140     dump_node(F, node);
1141     dump_ir_data_edges(F, node);
1142   }
1143
1144   /* Close the vcg information for the block */
1145   fprintf(F, "}\n");
1146   dump_const_node_local(F, block);
1147 #if DO_HEAPANALYSIS
1148   dump_chi_term(F, block);
1149 #endif
1150   fprintf(F, "\n");
1151 }
1152
1153 /** dumps a graph block-wise. Expects all blockless nodes in arr in irgs link.
1154  *  The outermost nodes: blocks and nodes not op_pin_state_pinned, Bad, Unknown. */
1155 static void
1156 dump_block_graph(FILE *F, ir_graph *irg) {
1157   int i;
1158   ir_graph *rem = current_ir_graph;
1159   ir_node **arr = ird_get_irg_link(irg);
1160   current_ir_graph = irg;
1161
1162   for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1163     ir_node * node = arr[i];
1164     if (is_Block(node)) {
1165       /* Dumps the block and all the nodes in the block, which are to
1166          be found in Block->link. */
1167       dump_whole_block(F, node);
1168     } else {
1169       /* Nodes that are not in a Block. */
1170       dump_node(F, node);
1171       dump_ir_data_edges(F, node);
1172     }
1173   }
1174
1175   if (dump_loop_information_flag) dump_loop_nodes_into_graph(F, irg);
1176
1177   current_ir_graph = rem;
1178 }
1179
1180 /** Dumps an irg as a graph.
1181  *  If interprocedural view edges can point to nodes out of this graph.
1182  */
1183 static void dump_graph(FILE *F, ir_graph *irg) {
1184
1185   fprintf(F, "graph: { title: \"");
1186   PRINT_IRGID(irg);
1187   fprintf(F, "\" label: \"%s\" status:clustered color:white \n",
1188       get_ent_dump_name(get_irg_entity(irg)));
1189
1190   dump_block_graph(F, irg);
1191
1192   /* Close the vcg information for the irg */
1193   fprintf(F, "}\n\n");
1194 }
1195
1196 /*******************************************************************/
1197 /* Basic type and entity nodes and edges.                          */
1198 /*******************************************************************/
1199
1200 /* dumps the edges between nodes and their type or entity attributes. */
1201 static void dump_node2type_edges(ir_node *n, void *env)
1202 {
1203   FILE *F = env;
1204   assert(n);
1205
1206   switch (get_irn_opcode(n)) {
1207   case iro_Const :
1208     /* @@@ some consts have an entity */
1209     break;
1210   case iro_SymConst:
1211     if (   (get_SymConst_kind(n) ==symconst_type_tag)
1212        || (get_SymConst_kind(n) ==symconst_size))
1213       {
1214         print_node_type_edge(F,n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
1215       }
1216     break;
1217   case iro_Sel: {
1218       print_node_ent_edge(F,n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
1219     } break;
1220   case iro_Call: {
1221       print_node_type_edge(F,n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
1222     } break;
1223   case iro_Alloc: {
1224       print_node_type_edge(F,n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
1225     } break;
1226   case iro_Free: {
1227       print_node_type_edge(F,n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
1228     } break;
1229   case iro_Cast: {
1230       print_node_type_edge(F,n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
1231     } break;
1232   default:
1233     break;
1234   }
1235 }
1236
1237
1238 static int print_type_info(FILE *F, type *tp) {
1239   int bad = 0;
1240
1241   if (get_type_state(tp) == layout_undefined) {
1242     fprintf(F, "state: layout_undefined\n");
1243   } else {
1244     fprintf(F, "state: layout_fixed,\n");
1245   }
1246   if (get_type_mode(tp))
1247     fprintf(F, "mode: %s,\n", get_mode_name_ex(get_type_mode(tp), &bad));
1248   fprintf(F, "size: %db,\n", get_type_size_bits(tp));
1249
1250   return bad;
1251 }
1252
1253 static void print_typespecific_info(FILE *F, type *tp) {
1254   switch (get_type_tpop_code(tp)) {
1255   case tpo_class:
1256     {
1257       fprintf(F, "peculiarity: %s\n", get_peculiarity_string(get_class_peculiarity(tp)));
1258     } break;
1259   case tpo_struct:
1260     {
1261     } break;
1262   case tpo_method:
1263     {
1264       fprintf(F, "variadicity: %s\n", get_variadicity_name(get_method_variadicity(tp)));
1265       fprintf(F, "params: %d\n", get_method_n_params(tp));
1266       fprintf(F, "results: %d\n", get_method_n_ress(tp));
1267     } break;
1268   case tpo_union:
1269     {
1270     } break;
1271   case tpo_array:
1272     {
1273     } break;
1274   case tpo_enumeration:
1275     {
1276     } break;
1277   case tpo_pointer:
1278     {
1279     } break;
1280   case tpo_primitive:
1281     {
1282     } break;
1283   default: break;
1284   } /* switch type */
1285 }
1286
1287
1288 static void print_typespecific_vcgattr(FILE *F, type *tp) {
1289   switch (get_type_tpop_code(tp)) {
1290   case tpo_class:
1291     {
1292       if (peculiarity_existent == get_class_peculiarity(tp))
1293     fprintf (F, " " TYPE_CLASS_NODE_ATTR);
1294       else
1295     fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
1296     } break;
1297   case tpo_struct:
1298     {
1299       fprintf (F, " " TYPE_METH_NODE_ATTR);
1300     } break;
1301   case tpo_method:
1302     {
1303     } break;
1304   case tpo_union:
1305     {
1306     } break;
1307   case tpo_array:
1308     {
1309     } break;
1310   case tpo_enumeration:
1311     {
1312     } break;
1313   case tpo_pointer:
1314     {
1315     } break;
1316   case tpo_primitive:
1317     {
1318     } break;
1319   default: break;
1320   } /* switch type */
1321 }
1322
1323 static int print_type_node(FILE *F, type *tp)
1324 {
1325   int bad = 0;
1326
1327   fprintf (F, "node: {title: ");
1328   PRINT_TYPEID(tp);
1329   fprintf (F, " label: \"%s %s\"", get_type_tpop_name(tp), get_type_name_ex(tp, &bad));
1330   fprintf (F, " info1: \"");
1331   bad |= print_type_info(F, tp);
1332   print_typespecific_info(F, tp);
1333   fprintf (F, "\"");
1334   print_typespecific_vcgattr(F, tp);
1335   fprintf (F, "}\n");
1336
1337   return bad;
1338 }
1339
1340 #define X(a)    case a: fprintf(F, #a); break
1341 void dump_entity_node(FILE *F, entity *ent)
1342 {
1343   fprintf (F, "node: {title: \"");
1344   PRINT_ENTID(ent); fprintf(F, "\"");
1345   fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
1346   fprintf (F, "label: ");
1347   fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent));
1348   fprintf (F, "\n info1: \"");
1349
1350   dump_entity_to_file(F, ent);
1351
1352   fprintf(F, "\"\n}\n");
1353 }
1354 #undef X
1355
1356 static void dump_enum_item(FILE *F, type *tp, int pos)
1357 {
1358   char buf[1024];
1359   ident *id  = get_enumeration_nameid(tp, pos);
1360   tarval *tv = get_enumeration_enum(tp, pos);
1361
1362   tarval_snprintf(buf, sizeof(buf), tv);
1363   fprintf (F, "node: {title: \"");
1364   PRINT_ITEMID(tp, pos); fprintf(F, "\"");
1365   fprintf (F, DEFAULT_ENUM_ITEM_ATTRIBUTE);
1366   fprintf (F, "label: ");
1367   fprintf (F, "\"enum item %s\" " ENUM_ITEM_NODE_ATTR, get_id_str(id));
1368   fprintf (F, "\n info1: \"value: %s\"}\n", buf);
1369 }
1370
1371 /* dumps a type or entity and it's edges. */
1372 static void
1373 dump_type_info(type_or_ent *tore, void *env) {
1374   FILE *F = env;
1375   int i = 0;  /* to shutup gcc */
1376
1377   /* dump this type or entity */
1378
1379   switch (get_kind(tore)) {
1380   case k_entity:
1381     {
1382       entity *ent = (entity *)tore;
1383       ir_node *value;
1384       /* The node */
1385       dump_entity_node(F, ent);
1386       /* The Edges */
1387       /* skip this to reduce graph.  Member edge of type is parallel to this edge. *
1388       fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1389                 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
1390       print_ent_type_edge(F,ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
1391       if(is_class_type(get_entity_owner(ent))) {
1392         for(i = 0; i < get_entity_n_overwrites(ent); i++)
1393           print_ent_ent_edge(F,ent, get_entity_overwrites(ent, i), 0, ENT_OVERWRITES_EDGE_ATTR);
1394       }
1395       /* attached subgraphs */
1396       if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
1397         if (is_atomic_entity(ent)) {
1398           value = get_atomic_ent_value(ent);
1399           if (value) {
1400             print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1401             /* DDMN(value);  $$$ */
1402             dump_const_expression(F, value);
1403           }
1404         }
1405         if (is_compound_entity(ent)) {
1406           for (i = 0; i < get_compound_ent_n_values(ent); i++) {
1407             value = get_compound_ent_value(ent, i);
1408             if (value) {
1409               print_ent_node_edge(F, ent, value, ENT_VALUE_EDGE_ATTR, i);
1410               dump_const_expression(F, value);
1411               print_ent_ent_edge(F, ent, get_compound_ent_value_member(ent, i), 0, ENT_CORR_EDGE_ATTR, i);
1412               /*
1413               fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
1414               ENT_CORR_EDGE_ATTR  "}\n", GET_ENTID(ent),
1415               get_compound_ent_value_member(ent, i), i);
1416               */
1417             }
1418           }
1419         }
1420       }
1421     } break;
1422   case k_type:
1423     {
1424       type *tp = (type *)tore;
1425       print_type_node(F, tp);
1426       /* and now the edges */
1427       switch (get_type_tpop_code(tp)) {
1428       case tpo_class:
1429         {
1430           for (i=0; i < get_class_n_supertypes(tp); i++)
1431             print_type_type_edge(F, tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1432           for (i=0; i < get_class_n_members(tp); i++)
1433             print_type_ent_edge(F,tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1434         } break;
1435       case tpo_struct:
1436         {
1437           for (i=0; i < get_struct_n_members(tp); i++)
1438             print_type_ent_edge(F,tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
1439         } break;
1440       case tpo_method:
1441         {
1442           for (i = 0; i < get_method_n_params(tp); i++)
1443             print_type_type_edge(F,tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
1444           for (i = 0; i < get_method_n_ress(tp); i++)
1445             print_type_type_edge(F,tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
1446         } break;
1447       case tpo_union:
1448         {
1449           for (i = 0; i < get_union_n_members(tp); i++)
1450             print_type_ent_edge(F,tp,get_union_member(tp, i),UNION_EDGE_ATTR);
1451         } break;
1452       case tpo_array:
1453         {
1454           print_type_type_edge(F,tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
1455           print_type_ent_edge(F,tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
1456           for (i = 0; i < get_array_n_dimensions(tp); i++) {
1457             ir_node *upper = get_array_upper_bound(tp, i);
1458             ir_node *lower = get_array_lower_bound(tp, i);
1459             print_node_type_edge(F, upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
1460             print_node_type_edge(F, lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
1461             dump_const_expression(F, upper);
1462             dump_const_expression(F, lower);
1463           }
1464
1465         } break;
1466       case tpo_enumeration:
1467         {
1468           for (i = 0; i < get_enumeration_n_enums(tp); ++i) {
1469             dump_enum_item(F, tp, i);
1470             print_enum_item_edge(F, tp, i, "label: \"item %d\"", i);
1471           }
1472         } break;
1473       case tpo_pointer:
1474         {
1475           print_type_type_edge(F,tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
1476         } break;
1477       case tpo_primitive:
1478         {
1479         } break;
1480       default: break;
1481       } /* switch type */
1482     }
1483     break; /* case k_type */
1484   default:
1485     {
1486       printf(" *** irdump,  dump_type_info(l.%i), faulty type.\n", __LINE__);
1487     } break;
1488   } /* switch kind_or_entity */
1489 }
1490
1491 typedef struct _h_env {
1492   int dump_ent;
1493   FILE *f;
1494 } h_env_t;
1495
1496 /** For dumping class hierarchies.
1497  * Dumps a class type node and a superclass edge.
1498  * If env->dump_ent dumps entities of classes and overwrites edges.
1499  */
1500 static void
1501 dump_class_hierarchy_node (type_or_ent *tore, void *ctx) {
1502   h_env_t *env = ctx;
1503   FILE *F = env->f;
1504   int i = 0;  /* to shutup gcc */
1505
1506   /* dump this type or entity */
1507   switch (get_kind(tore)) {
1508   case k_entity: {
1509     entity *ent = (entity *)tore;
1510     if (get_entity_owner(ent) == get_glob_type()) break;
1511     if (!is_method_type(get_entity_type(ent))) break;  /* GL */
1512     if (env->dump_ent && is_class_type(get_entity_owner(ent))) {
1513       /* The node */
1514       dump_entity_node(F, ent);
1515       /* The edges */
1516       print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
1517       for(i = 0; i < get_entity_n_overwrites(ent); i++)
1518         print_ent_ent_edge(F, get_entity_overwrites(ent, i), ent, 0, ENT_OVERWRITES_EDGE_ATTR);
1519     }
1520   } break; /* case k_entity */
1521   case k_type:
1522     {
1523       type *tp = (type *)tore;
1524       if (tp == get_glob_type()) break;
1525       switch (get_type_tpop_code(tp)) {
1526         case tpo_class: {
1527           print_type_node(F, tp);
1528           /* and now the edges */
1529           for (i=0; i < get_class_n_supertypes(tp); i++)
1530           {
1531               print_type_type_edge(F,tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
1532           }
1533         } break;
1534         default: break;
1535       } /* switch type */
1536     }
1537     break; /* case k_type */
1538   default:
1539     {
1540       printf(" *** irdump,  dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
1541     } break;
1542   } /* switch kind_or_entity */
1543 }
1544
1545 /*******************************************************************/
1546 /* dump analysis information that is expressed in graph terms.     */
1547 /*******************************************************************/
1548
1549 /* dump out edges */
1550 static void
1551 dump_out_edge(ir_node *n, void *env) {
1552   FILE *F = env;
1553   int i;
1554   for (i = 0; i < get_irn_n_outs(n); i++) {
1555     assert(get_irn_out(n, i));
1556     fprintf (F, "edge: {sourcename: \"");
1557     PRINT_NODEID(n);
1558     fprintf (F, "\" targetname: \"");
1559     PRINT_NODEID(get_irn_out(n, i));
1560     fprintf (F, "\" color: red linestyle: dashed");
1561     fprintf (F, "}\n");
1562   }
1563 }
1564
1565 static INLINE void
1566 dump_loop_label(FILE *F, ir_loop *loop) {
1567   fprintf (F, "loop %d, %d sons, %d nodes",
1568        get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
1569 }
1570
1571 static INLINE void dump_loop_info(FILE *F, ir_loop *loop) {
1572   fprintf (F, " info1: \"");
1573   fprintf (F, " loop nr: %d", get_loop_loop_nr(loop));
1574 #if DEBUG_libfirm   /* GL @@@ debug analyses */
1575   fprintf (F, "\n The loop was analyzed %d times.", (int)get_loop_link(loop));
1576 #endif
1577   fprintf (F, "\"");
1578 }
1579
1580 static INLINE void
1581 dump_loop_node(FILE *F, ir_loop *loop) {
1582   fprintf (F, "node: {title: \"");
1583   PRINT_LOOPID(loop);
1584   fprintf (F, "\" label: \"");
1585   dump_loop_label(F, loop);
1586   fprintf (F, "\" ");
1587   dump_loop_info(F, loop);
1588   fprintf (F, "}\n");
1589
1590 }
1591
1592 static INLINE void
1593 dump_loop_node_edge(FILE *F, ir_loop *loop, int i) {
1594   assert(loop);
1595   fprintf (F, "edge: {sourcename: \"");
1596   PRINT_LOOPID(loop);
1597   fprintf (F, "\" targetname: \"");
1598   PRINT_NODEID(get_loop_node(loop, i));
1599   fprintf (F, "\" color: green");
1600   fprintf (F, "}\n");
1601 }
1602
1603 static INLINE void
1604 dump_loop_son_edge(FILE *F, ir_loop *loop, int i) {
1605   assert(loop);
1606   fprintf (F, "edge: {sourcename: \"");
1607   PRINT_LOOPID(loop);
1608   fprintf (F, "\" targetname: \"");
1609   PRINT_LOOPID(get_loop_son(loop, i));
1610   fprintf (F, "\" color: darkgreen label: \"%d\"}\n",
1611        get_loop_element_pos(loop, get_loop_son(loop, i)));
1612 }
1613
1614 static
1615 void dump_loops(FILE *F, ir_loop *loop) {
1616   int i;
1617   /* dump this loop node */
1618   dump_loop_node(F, loop);
1619
1620   /* dump edges to nodes in loop -- only if it is a real loop */
1621   if (get_loop_depth(loop) != 0) {
1622     for (i = 0; i < get_loop_n_nodes(loop); i++) {
1623       dump_loop_node_edge(F, loop, i);
1624     }
1625   }
1626   for (i = 0; i < get_loop_n_sons(loop); i++) {
1627     dump_loops(F, get_loop_son(loop, i));
1628     dump_loop_son_edge(F, loop, i);
1629   }
1630 }
1631
1632 static INLINE
1633 void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg) {
1634   ir_graph *rem = current_ir_graph;
1635   current_ir_graph = irg;
1636
1637   if (get_irg_loop(irg)) dump_loops(F, get_irg_loop(irg));
1638
1639   current_ir_graph = rem;
1640 }
1641
1642
1643 /**
1644  * dumps the VCG header
1645  */
1646 static INLINE void
1647 dump_vcg_header(FILE *F, const char *name, const char *orientation) {
1648   char *label;
1649
1650   if (edge_label) {
1651     label = "yes";
1652   } else {
1653     label = "no";
1654   }
1655
1656   if (!orientation) orientation = "bottom_to_top";
1657
1658   /* print header */
1659   fprintf (F,
1660        "graph: { title: \"ir graph of %s\"\n"
1661        "display_edge_labels: %s\n"
1662        "layoutalgorithm: mindepth\n"
1663        "manhattan_edges: yes\n"
1664        "port_sharing: no\n"
1665        "orientation: %s\n"
1666        "classname 1:  \"intrablock Data\"\n"
1667        "classname 16: \"interblock Data\"\n"
1668        "classname 2:  \"Block\"\n"
1669        "classname 13: \"Control Flow\"\n"
1670        "classname 14: \"intrablock Memory\"\n"
1671        "classname 17: \"interblock Memory\"\n"
1672        "classname 15: \"Dominators\"\n"
1673        "classname 3:  \"Entity type\"\n"
1674        "classname 4:  \"Entity owner\"\n"
1675        "classname 5:  \"Method Param\"\n"
1676        "classname 6:  \"Method Res\"\n"
1677        "classname 7:  \"Super\"\n"
1678        "classname 8:  \"Union\"\n"
1679        "classname 9:  \"Points-to\"\n"
1680        "classname 10: \"Array Element Type\"\n"
1681        "classname 11: \"Overwrites\"\n"
1682        "classname 12: \"Member\"\n"
1683        "infoname 1: \"Attribute\"\n"
1684        "infoname 2: \"Verification errors\"\n",
1685        name, label, orientation);
1686
1687   fprintf (F, "\n");        /* a separator */
1688 }
1689
1690 /**
1691  * open a vcg file
1692  *
1693  * @param irg     The graph to be dumped
1694  * @param suffix1 first filename suffix
1695  * @param suffix2 second filename suffix
1696  */
1697 static FILE *vcg_open (ir_graph *irg, const char * suffix1, const char *suffix2) {
1698   FILE *F;
1699   const char *nm = get_irg_dump_name(irg);
1700   int len = strlen(nm), i, j;
1701   char *fname;  /* filename to put the vcg information in */
1702
1703   if (!suffix1) suffix1 = "";
1704   if (!suffix2) suffix2 = "";
1705
1706   /* open file for vcg graph */
1707   fname = malloc (len * 2 + strlen(suffix1) + strlen(suffix2) + 5);
1708
1709   /* strncpy (fname, nm, len); */     /* copy the filename */
1710   j = 0;
1711   for (i = 0; i < len; ++i) {  /* replase '/' in the name: escape by @. */
1712     if (nm[i] == '/') {
1713       fname[j] = '@'; j++; fname[j] = '1'; j++;
1714     } else if (nm[i] == '@') {
1715       fname[j] = '@'; j++; fname[j] = '2'; j++;
1716     } else {
1717       fname[j] = nm[i]; j++;
1718     }
1719   }
1720   fname[j] = '\0';
1721   strcat (fname, suffix1);  /* append file suffix */
1722   strcat (fname, suffix2);  /* append file suffix */
1723   strcat (fname, ".vcg");   /* append the .vcg suffix */
1724   F = fopen (fname, "w");   /* open file for writing */
1725   if (!F) {
1726     panic("cannot open %s for writing (%m)", fname);  /* not reached */
1727   }
1728   free(fname);
1729
1730   return F;
1731 }
1732
1733 /**
1734  * open a vcg file
1735  *
1736  * @param irg     The graph to be dumped
1737  * @param suffix  filename suffix
1738  */
1739 static FILE *vcg_open_name (const char *name, const char *suffix) {
1740   FILE *F;
1741   char *fname;  /* filename to put the vcg information in */
1742   int i, j, len = strlen(name);
1743
1744   if (!suffix) suffix = "";
1745
1746   /** open file for vcg graph */
1747   fname = malloc (len * 2 + 5 + strlen(suffix));
1748   /* strcpy (fname, name);*/    /* copy the filename */
1749   j = 0;
1750   for (i = 0; i < len; ++i) {  /* replase '/' in the name: escape by @. */
1751     if (name[i] == '/') {
1752       fname[j] = '@'; j++; fname[j] = '1'; j++;
1753     } else if (name[i] == '@') {
1754       fname[j] = '@'; j++; fname[j] = '2'; j++;
1755     } else {
1756       fname[j] = name[i]; j++;
1757     }
1758   }
1759   fname[j] = '\0';
1760   strcat (fname, suffix);
1761   strcat (fname, ".vcg");  /* append the .vcg suffix */
1762   F = fopen (fname, "w");  /* open file for writing */
1763   if (!F) {
1764     panic ("cannot open %s for writing (%m)", fname);  /* not reached */
1765   }
1766   free(fname);
1767
1768   return F;
1769 }
1770
1771 /**
1772  * Dumps the vcg file footer
1773  */
1774 static INLINE void dump_vcg_footer (FILE *F) {
1775   fprintf (F, "}\n");
1776 }
1777
1778 /**
1779  * close the vcg file
1780  */
1781 static void
1782 vcg_close (FILE *F) {
1783   dump_vcg_footer(F);    /* print footer */
1784   fclose (F);           /* close vcg file */
1785 }
1786
1787 /************************************************************************/
1788 /************************************************************************/
1789 /* Routines that dump all or parts of the firm representation to a file */
1790 /************************************************************************/
1791 /************************************************************************/
1792
1793 /************************************************************************/
1794 /* Dump ir graphs, differnt formats and additional information.         */
1795 /************************************************************************/
1796
1797 /** Routine to dump a graph, blocks as conventional nodes.
1798  */
1799 void
1800 dump_ir_graph (ir_graph *irg, const char *suffix )
1801 {
1802   FILE *f;
1803   ir_graph *rem;
1804   char *suffix1;
1805   rem = current_ir_graph;
1806
1807   if(strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter))!=0) return;
1808   current_ir_graph = irg;
1809   if (interprocedural_view) suffix1 = "-pure-ip";
1810   else                      suffix1 = "-pure";
1811   f = vcg_open(irg, suffix, suffix1);
1812   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1813
1814   /* walk over the graph */
1815   /* dump_whole_node must be called in post visiting predecessors */
1816   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1817
1818   /* dump the out edges in a separate walk */
1819   if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != outs_none)) {
1820     irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1821   }
1822
1823   vcg_close(f);
1824
1825   current_ir_graph = rem;
1826 }
1827
1828
1829 void
1830 dump_ir_block_graph (ir_graph *irg, const char *suffix)
1831 {
1832   FILE *f;
1833   int i;
1834   char *suffix1;
1835
1836   if(strncmp(get_entity_name(get_irg_entity(irg)),dump_file_filter,strlen(dump_file_filter))!=0) return;
1837   if (interprocedural_view) suffix1 = "-ip";
1838   else                      suffix1 = "";
1839   f = vcg_open(irg, suffix, suffix1);
1840   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1841
1842   construct_block_lists(irg);
1843
1844   for (i = 0; i < get_irp_n_irgs(); i++) {
1845     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1846     if (arr) {
1847       dump_graph(f, get_irp_irg(i));
1848       DEL_ARR_F(arr);
1849     }
1850   }
1851
1852   vcg_close(f);
1853 }
1854
1855 /** dumps a graph with type information
1856  */
1857 void
1858 dump_ir_graph_w_types (ir_graph *irg, const char *suffix)
1859 {
1860   FILE *f;
1861   ir_graph *rem = current_ir_graph;
1862   char *suffix1;
1863
1864   /* if a filter is set, dump only the irg's that match the filter */
1865   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1866     return;
1867
1868   current_ir_graph = irg;
1869
1870   if (interprocedural_view) suffix1 = "-pure-wtypes-ip";
1871   else                      suffix1 = "-pure-wtypes";
1872   f = vcg_open(irg,suffix, suffix1);
1873   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1874
1875   /* dump common ir graph */
1876   irg_walk(get_irg_end(irg), NULL, dump_whole_node, f);
1877   /* dump type info */
1878   type_walk_irg(irg, dump_type_info, NULL, f);
1879   inc_irg_visited(get_const_code_irg());
1880   /* dump edges from graph to type info */
1881   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1882
1883   vcg_close(f);
1884   current_ir_graph = rem;
1885 }
1886
1887 void
1888 dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix)
1889 {
1890   FILE *f;
1891   int i;
1892   char *suffix1;
1893   ir_graph *rem = current_ir_graph;
1894
1895   /* if a filter is set, dump only the irg's that match the filter */
1896   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1897     return;
1898
1899   if (interprocedural_view) suffix1 = "-wtypes-ip";
1900   else                      suffix1 = "-wtypes";
1901   f = vcg_open(irg, suffix, suffix1);
1902   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1903
1904   /* dump common blocked ir graph */
1905   construct_block_lists(irg);
1906
1907   for (i = 0; i < get_irp_n_irgs(); i++) {
1908     ir_node **arr = ird_get_irg_link(get_irp_irg(i));
1909     if (arr) {
1910       dump_graph(f, get_irp_irg(i));
1911       DEL_ARR_F(arr);
1912     }
1913   }
1914
1915   /* dump type info */
1916   current_ir_graph = irg;
1917   type_walk_irg(irg, dump_type_info, NULL, f);
1918   inc_irg_visited(get_const_code_irg());
1919
1920   /* dump edges from graph to type info */
1921   irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, f);
1922
1923   current_ir_graph = rem;
1924   vcg_close(f);
1925 }
1926
1927 /***********************************************************************/
1928 /* The following routines dump a control flow graph.                   */
1929 /***********************************************************************/
1930
1931 static void
1932 dump_block_to_cfg(ir_node *block, void *env) {
1933   FILE *F = env;
1934   int i;
1935   ir_node *pred;
1936
1937   if (is_Block(block)) {
1938     /* This is a block. Dump a node for the block. */
1939     fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1940     fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1941     PRINT_NODEID(block);
1942     fprintf (F, "\" ");
1943     if (dump_dominator_information_flag)
1944       fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1945     fprintf (F, "}\n");
1946     /* Dump the edges */
1947     for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1948       if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1949     pred = get_nodes_block(skip_Proj(get_Block_cfgpred(block, i)));
1950     fprintf (F, "edge: { sourcename: \"");
1951     PRINT_NODEID(block);
1952     fprintf (F, "\" targetname: \"");
1953     PRINT_NODEID(pred);
1954     fprintf (F, "\"}\n");
1955       }
1956
1957     /* Dump dominator edge */
1958     if (dump_dominator_information_flag && get_Block_idom(block)) {
1959       pred = get_Block_idom(block);
1960       fprintf (F, "edge: { sourcename: \"");
1961       PRINT_NODEID(block);
1962       fprintf (F, "\" targetname: \"");
1963       PRINT_NODEID(pred);
1964       fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1965     }
1966   }
1967 }
1968
1969 void
1970 dump_cfg (ir_graph *irg, const char *suffix)
1971 {
1972   FILE *f;
1973   ir_graph *rem = current_ir_graph;
1974   int ddif = dump_dominator_information_flag;
1975   int ipv = interprocedural_view;
1976
1977   /* if a filter is set, dump only the irg's that match the filter */
1978   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
1979     return;
1980
1981   current_ir_graph = irg;
1982
1983   f = vcg_open(irg, suffix, "-cfg");
1984   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
1985
1986   if (interprocedural_view) {
1987     printf("Warning: dumping cfg not in interprocedural view!\n");
1988     interprocedural_view = 0;
1989   }
1990
1991   if (get_irg_dom_state(irg) != dom_consistent)
1992     dump_dominator_information_flag = 0;
1993
1994   /* walk over the blocks in the graph */
1995   irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
1996   dump_node(f, get_irg_bad(irg));
1997
1998   dump_dominator_information_flag = ddif;
1999   interprocedural_view = ipv;
2000   vcg_close(f);
2001   current_ir_graph = rem;
2002 }
2003
2004 void dump_callgraph(const char *suffix) {
2005   FILE *F;
2006   int i, n_irgs = get_irp_n_irgs();
2007   int rem = edge_label;
2008   edge_label = 1;
2009
2010   my_special_flag = 1;
2011
2012   F = vcg_open_name("Callgraph", suffix);
2013   dump_vcg_header(F, "Callgraph", NULL);
2014
2015   for (i = 0; i < n_irgs; ++i) {
2016     ir_graph *irg = get_irp_irg(i);
2017     entity *ent = get_irg_entity(irg);
2018     int j, n_callees = get_irg_n_callees(irg);
2019
2020     dump_entity_node(F, ent);
2021     for (j = 0; j < n_callees; ++j) {
2022       entity *c = get_irg_entity(get_irg_callee(irg, j));
2023       int be = is_irg_callee_backedge(irg, j);
2024       char *attr;
2025       attr = (be) ?
2026         "label:\"recursion %d\" color:red" :
2027         "label:\"calls %d\"";
2028       print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j));
2029     }
2030   }
2031
2032   my_special_flag = 0;
2033   edge_label = rem;
2034   vcg_close(F);
2035 }
2036
2037 /* Dump all irgs in interprocedural view to a single file. */
2038 void dump_all_cg_block_graph(const char *suffix) {
2039   FILE *f;
2040   int i;
2041   int rem_view = interprocedural_view;
2042   interprocedural_view = 1;
2043
2044   f = vcg_open_name("All_graphs", suffix);
2045   dump_vcg_header(f, "All_graphs", NULL);
2046
2047   /* collect nodes in all irgs reachable in call graph*/
2048   for (i = 0; i < get_irp_n_irgs(); i++)
2049     ird_set_irg_link(get_irp_irg(i), NULL);
2050
2051   cg_walk(clear_link, collect_node, NULL);
2052
2053   /* dump all graphs */
2054   for (i = 0; i < get_irp_n_irgs(); i++) {
2055     current_ir_graph = get_irp_irg(i);
2056     assert(ird_get_irg_link(current_ir_graph));
2057     dump_graph(f, current_ir_graph);
2058     DEL_ARR_F(ird_get_irg_link(current_ir_graph));
2059   }
2060
2061   vcg_close(f);
2062   interprocedural_view = rem_view;
2063 }
2064
2065 /***********************************************************************/
2066 /* the following routines dumps type information without any ir nodes. */
2067 /***********************************************************************/
2068
2069 void
2070 dump_type_graph (ir_graph *irg, const char *suffix)
2071 {
2072   FILE *f;
2073   ir_graph *rem;
2074   rem = current_ir_graph;
2075
2076   /* if a filter is set, dump only the irg's that match the filter */
2077   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return;
2078
2079   current_ir_graph = irg;
2080
2081   f = vcg_open(irg, suffix, "-type");
2082   dump_vcg_header(f, get_irg_dump_name(irg), NULL);
2083
2084   /* walk over the blocks in the graph */
2085   type_walk_irg(irg, dump_type_info, NULL, f);
2086   /* The walker for the const code can be called several times for the
2087      same (sub) experssion.  So that no nodes are dumped several times
2088      we decrease the visited flag of the corresponding graph after each
2089      walk.  So now increase it finally. */
2090   inc_irg_visited(get_const_code_irg());
2091
2092   vcg_close(f);
2093   current_ir_graph = rem;
2094 }
2095
2096 void
2097 dump_all_types (const char *suffix)
2098 {
2099   FILE *f = vcg_open_name("All_types", suffix);
2100   dump_vcg_header(f, "All_types", NULL);
2101   type_walk(dump_type_info, NULL, f);
2102   inc_irg_visited(get_const_code_irg());
2103   vcg_close(f);
2104 }
2105
2106 void
2107 dump_class_hierarchy (bool entities, const char *suffix)
2108 {
2109   FILE *f = vcg_open_name("class_hierarchy", suffix);
2110   h_env_t env;
2111
2112   env.f = f;
2113   dump_vcg_header(f, "class_hierarchy", NULL);
2114   if (entities)
2115     env.dump_ent = 1;
2116   else
2117     env.dump_ent = 0;
2118   type_walk(dump_class_hierarchy_node, NULL, &env);
2119   vcg_close(f);
2120 }
2121
2122 /***********************************************************************/
2123 /* dumps all graphs with the graph-dumper passed. Possible dumpers:    */
2124 /*  dump_ir_graph                                                      */
2125 /*  dump_ir_block_graph                                                */
2126 /*  dump_cfg                                                           */
2127 /*  dump_type_graph                                                    */
2128 /*  dump_ir_graph_w_types                                              */
2129 /***********************************************************************/
2130
2131 void dump_all_ir_graphs(dump_graph_func *dmp_grph, const char *suffix) {
2132   int i;
2133   for (i=0; i < get_irp_n_irgs(); i++) {
2134     dmp_grph(get_irp_irg(i), suffix);
2135   }
2136 }
2137
2138
2139 /**********************************************************************************
2140  * Dumps a stand alone loop graph with firm nodes which belong to one loop nodes  *
2141  * packed together in one subgraph/box                                            *
2142  **********************************************************************************/
2143
2144 void dump_loops_standalone(FILE *F, ir_loop *loop) {
2145   int i = 0, loop_node_started = 0, son_number = 0, first = 0;
2146   loop_element le;
2147   ir_loop *son = NULL;
2148
2149   /* Dump a new loop node. */
2150   dump_loop_node(F, loop);
2151
2152   /* Dump the loop elements. */
2153
2154   for(i = 0; i < get_loop_n_elements(loop); i++) {
2155     le = get_loop_element(loop, i);
2156     son = le.son;
2157     if (get_kind(son) == k_ir_loop) {
2158
2159       /* We are a loop son -> Recurse */
2160
2161       if(loop_node_started) { /* Close the "firm-nodes" node first if we started one. */
2162         fprintf(F, "\" }\n");
2163         fprintf (F, "edge: {sourcename: \"");
2164         PRINT_LOOPID(loop);
2165         fprintf (F, "\" targetname: \"");
2166         PRINT_LOOPID(loop);
2167         fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2168         loop_node_started = 0;
2169       }
2170       dump_loop_son_edge(F, loop, son_number++);
2171       dump_loops_standalone(F, son);
2172     } else if (get_kind(son) == k_ir_node) {
2173         /* We are a loop node -> Collect firm nodes */
2174
2175       ir_node *n = le.node;
2176       int bad = 0;
2177
2178       if (!loop_node_started) {
2179         /* Start a new node which contains all firm nodes of the current loop */
2180         fprintf (F, "node: { title: \"");
2181         PRINT_LOOPID(loop);
2182         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2183         loop_node_started = 1;
2184         first = i;
2185       }
2186       else
2187         fprintf(F, "\n");
2188
2189       bad |= dump_node_opcode(F, n);
2190       bad |= dump_node_mode(F, n);
2191       bad |= dump_node_typeinfo(F, n);
2192       fprintf (F, " ");
2193       bad |= dump_node_nodeattr(F, n);
2194       fprintf (F, " %ld", get_irn_node_nr(n));
2195       if (is_Block(n)) fprintf (F, "\t ->%d", (int)get_irn_link(n));
2196     } else { /* for callgraph loop tree */
2197       assert(get_kind(son) == k_ir_graph);
2198       /* We are a loop node -> Collect firm graphs */
2199       ir_graph *n = (ir_graph *)le.node;
2200       if (!loop_node_started) {
2201         /* Start a new node which contains all firm nodes of the current loop */
2202         fprintf (F, "node: { title: \"");
2203         PRINT_LOOPID(loop);
2204         fprintf (F, "-%d-nodes\" color: lightyellow label: \"", i);
2205         loop_node_started = 1;
2206         first = i;
2207       }
2208       else
2209         fprintf(F, "\n");
2210       fprintf (F, " %s", get_irg_dump_name(n));
2211       /* fprintf (F, " %s (depth %d)", get_irg_dump_name(n), n->callgraph_weighted_loop_depth); */
2212     }
2213   }
2214
2215   if (loop_node_started) {
2216     fprintf(F, "\" }\n");
2217     fprintf (F, "edge: {sourcename: \"");
2218     PRINT_LOOPID(loop);
2219     fprintf (F, "\" targetname: \"");
2220     PRINT_LOOPID(loop);
2221     fprintf (F, "-%d-nodes\" label:\"%d...%d\"}\n", first, first, i-1);
2222     loop_node_started = 0;
2223   }
2224 }
2225
2226 void dump_loop_tree(ir_graph *irg, const char *suffix)
2227 {
2228   FILE *f;
2229   ir_graph *rem = current_ir_graph;
2230   int el_rem = edge_label;
2231   edge_label = 1;
2232
2233   /* if a filter is set, dump only the irg's that match the filter */
2234   if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0)
2235     return;
2236
2237   current_ir_graph = irg;
2238
2239   f = vcg_open(irg, suffix, "-looptree");
2240   dump_vcg_header(f, get_irg_dump_name(irg), "top_to_bottom");
2241
2242   if (get_irg_loop(irg)) dump_loops_standalone(f, get_irg_loop(irg));
2243
2244   vcg_close(f);
2245
2246   edge_label = el_rem;
2247   current_ir_graph = rem;
2248 }
2249
2250 void dump_callgraph_loop_tree(char *suffix) {
2251   FILE *F;
2252   F = vcg_open_name("Callgraph_looptree", suffix);
2253   dump_vcg_header(F, "callgraph looptree", "top_to_bottom");
2254   dump_loops_standalone(F, irp->outermost_cg_loop);
2255   vcg_close(F);
2256 }
2257
2258
2259 /*******************************************************************************/
2260 /* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
2261 /*******************************************************************************/
2262
2263 void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
2264   int i, son_number = 0, node_number = 0;
2265
2266   if (dump_loop_information_flag) dump_loop_node(F, loop);
2267
2268   for (i = 0; i < get_loop_n_elements(loop); i++) {
2269     loop_element le = get_loop_element(loop, i);
2270     if (*(le.kind) == k_ir_loop) {
2271       if (dump_loop_information_flag) dump_loop_son_edge(F, loop, son_number++);
2272       /* Recur */
2273       collect_nodeloop(F, le.son, loopnodes);
2274     } else {
2275       if (dump_loop_information_flag) dump_loop_node_edge(F, loop, node_number++);
2276       eset_insert(loopnodes, le.node);
2277     }
2278   }
2279 }
2280
2281 void collect_nodeloop_external_nodes(ir_loop *loop, eset *loopnodes, eset *extnodes) {
2282   int i, j, start;
2283
2284   for(i = 0; i < get_loop_n_elements(loop); i++) {
2285     loop_element le = get_loop_element(loop, i);
2286     if (*(le.kind) == k_ir_loop) {
2287       /* Recur */
2288       collect_nodeloop_external_nodes(le.son, loopnodes, extnodes);
2289     } else {
2290       if (is_Block(le.node)) start = 0; else start = -1;
2291       for (j = start; j < get_irn_arity(le.node); j++) {
2292         ir_node *pred = get_irn_n(le.node, j);
2293         if (!eset_contains(loopnodes, pred)) {
2294           eset_insert(extnodes, pred);
2295           if (!is_Block(pred)) {
2296             pred = get_nodes_block(pred);
2297             if (!eset_contains(loopnodes, pred)) eset_insert(extnodes, pred);
2298           }
2299         }
2300       }
2301     }
2302   }
2303 }
2304
2305 void dump_loop(ir_loop *l, const char *suffix) {
2306   FILE *F;
2307   char name[50];
2308   eset *loopnodes = eset_create();
2309   eset *extnodes = eset_create();
2310   ir_node *n, *b;
2311
2312   snprintf(name, sizeof(name), "loop_%d", get_loop_loop_nr(l));
2313   F = vcg_open_name (name, suffix);
2314   dump_vcg_header(F, name, NULL);
2315
2316   /* collect all nodes to dump */
2317   collect_nodeloop(F, l, loopnodes);
2318   collect_nodeloop_external_nodes(l, loopnodes, extnodes);
2319
2320   /* build block lists */
2321   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2322     set_irn_link(n, NULL);
2323   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2324     set_irn_link(n, NULL);
2325   for (n = eset_first(loopnodes); n != NULL; n = eset_next(loopnodes))
2326     if (!is_Block(n)) {
2327       b = get_nodes_block(n);
2328       set_irn_link(n, get_irn_link(b));
2329       set_irn_link(b, n);
2330     }
2331   for (n = eset_first(extnodes); n != NULL; n = eset_next(extnodes))
2332     if (!is_Block(n)) {
2333       b = get_nodes_block(n);
2334       set_irn_link(n, get_irn_link(b));
2335       set_irn_link(b, n);
2336     }
2337
2338   for (b = eset_first(loopnodes); b != NULL; b = eset_next(loopnodes))
2339     if (is_Block(b)) {
2340       fprintf(F, "graph: { title: \"");
2341       PRINT_NODEID(b);
2342       fprintf(F, "\"  label: \"");
2343       dump_node_opcode(F, b);
2344       fprintf (F, " %ld", get_irn_node_nr(b));
2345       fprintf(F, "\" status:clustered color:yellow\n");
2346
2347       /* dump the blocks edges */
2348       dump_ir_data_edges(F, b);
2349
2350       /* dump the nodes that go into the block */
2351       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2352         if (eset_contains(extnodes, n)) overrule_nodecolor = "lightblue";
2353         dump_node(F, n);
2354         overrule_nodecolor = NULL;
2355         if (!eset_contains(extnodes, n)) dump_ir_data_edges(F, n);
2356       }
2357
2358       /* Close the vcg information for the block */
2359       fprintf(F, "}\n");
2360       dump_const_node_local(F, b);
2361       fprintf(F, "\n");
2362     }
2363   for (b = eset_first(extnodes); b != NULL; b = eset_next(extnodes))
2364     if (is_Block(b)) {
2365       fprintf(F, "graph: { title: \"");
2366       PRINT_NODEID(b);
2367       fprintf(F, "\"  label: \"");
2368       dump_node_opcode(F, b);
2369       fprintf (F, " %ld", get_irn_node_nr(b));
2370       fprintf(F, "\" status:clustered color:lightblue\n");
2371
2372       /* dump the nodes that go into the block */
2373       for (n = get_irn_link(b); n; n = get_irn_link(n)) {
2374         if (!eset_contains(loopnodes, n)) overrule_nodecolor = "lightblue";
2375         dump_node(F, n);
2376         overrule_nodecolor = NULL;
2377         if (eset_contains(loopnodes, n)) dump_ir_data_edges(F, n);
2378       }
2379
2380       /* Close the vcg information for the block */
2381       fprintf(F, "}\n");
2382       dump_const_node_local(F, b);
2383       fprintf(F, "\n");
2384     }
2385
2386   eset_destroy(loopnodes);
2387   eset_destroy(extnodes);
2388   vcg_close(F);
2389 }