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