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