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