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