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