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