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