fixed some depencies between irdump.c and irdumptxt.c
[libfirm] / ir / ir / irdumptxt.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/irdump.c
4  * Purpose:     Write vcg representation of firm to file.
5  * Author:      Martin Trapp, Christian Schaefer
6  * Modified by: Goetz Lindenmaier, Hubert Schmidt
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2003 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 #include <string.h>
14 #include <stdlib.h>
15 #include <stdarg.h>
16
17 #include "irdump_t.h"
18
19 #include "firm_common_t.h"
20
21 #include "irgraph_t.h"
22 #include "irprog_t.h"
23 #include "entity_t.h"
24 #include "trouts.h"
25
26 #include "field_temperature.h"
27
28 #define MY_SIZE 32     /* Size of an array that actually should be computed. */
29
30 int dump_node_opcode(FILE *F, ir_node *n); /* from irdump.c */
31
32
33
34 int addr_is_alloc(ir_node *acc) {
35   ir_node *addr = NULL;
36   opcode addr_op;
37   if (is_memop(acc)) {
38     addr = get_memop_ptr(acc);
39   } else {
40     assert(get_irn_op(acc) == op_Call);
41     addr = get_Call_ptr(acc);
42   }
43
44   addr_op = get_irn_opcode(addr);
45
46   while (addr_op != iro_Alloc) {
47
48     switch (addr_op) {
49     case iro_Sel:
50       addr = get_Sel_ptr(addr);
51       break;
52     case iro_Cast:
53       addr = get_Cast_op(addr);
54       break;
55     case iro_Proj:
56       addr = get_Proj_pred(addr);
57       break;
58     case iro_SymConst:
59     case iro_Const:
60       return 0;
61       break;
62     case iro_Phi:
63     case iro_Load:
64     case iro_Call:
65     case iro_Start:
66       return 0;
67       break;
68
69     default:
70       DDMN(addr);
71       assert(0 && "unexpected address node");
72     }
73     addr_op = get_irn_opcode(addr);
74   }
75
76   /* In addition, the alloc must be in the same loop. */
77
78   return 1;
79 }
80
81 #define X(a)    case a: fprintf(F, #a); break
82 void    dump_entity_to_file_prefix (FILE *F, entity *ent, char *prefix, unsigned verbosity) {
83   int i, j;
84   assert(ent && ent->kind == k_entity);
85   type *owner = get_entity_owner(ent);
86   type *type  = get_entity_type(ent);
87   if (verbosity & dump_verbosity_onlynames) {
88     fprintf(F, "%sentity %s.%s (%ld)\n", prefix, get_type_name(get_entity_owner(ent)),
89             get_entity_name(ent), get_entity_nr(ent));
90     return;
91   }
92
93   if (verbosity & dump_verbosity_entattrs) {
94     fprintf(F, "%sentity %s (%ld)\n", prefix, get_entity_name(ent), get_entity_nr(ent));
95     fprintf(F, "%s  type:  %s (%ld)\n", prefix, get_type_name(type),  get_type_nr(type));
96     fprintf(F, "%s  owner: %s (%ld)\n", prefix, get_type_name(owner), get_type_nr(owner));
97
98     if (is_class_type(get_entity_owner(ent))) {
99       if (get_entity_n_overwrites(ent) > 0) {
100         fprintf(F, "%s  overwrites:\n", prefix);
101         for (i = 0; i < get_entity_n_overwrites(ent); ++i) {
102           entity *ov = get_entity_overwrites(ent, i);
103           fprintf(F, "%s    %d: %s of class %s\n", prefix, i, get_entity_name(ov),
104                   get_type_name(get_entity_owner(ov)));
105         }
106       } else {
107         fprintf(F, "%s  Does not overwrite other entities. \n", prefix);
108       }
109       if (get_entity_n_overwrittenby(ent) > 0) {
110         fprintf(F, "%s  overwritten by:\n", prefix);
111         for (i = 0; i < get_entity_n_overwrittenby(ent); ++i) {
112           entity *ov = get_entity_overwrittenby(ent, i);
113           fprintf(F, "%s    %d: %s of class %s\n", prefix, i, get_entity_name(ov),
114                   get_type_name(get_entity_owner(ov)));
115         }
116       } else {
117         fprintf(F, "%s  Is not overwritten by other entities. \n", prefix);
118       }
119     }
120
121     fprintf(F, "%s  allocation:  ", prefix);
122     switch (get_entity_allocation(ent)) {
123       X(allocation_dynamic);
124       X(allocation_automatic);
125       X(allocation_static);
126       X(allocation_parameter);
127     }
128
129     fprintf(F, "\n%s  visibility:  ", prefix);
130     switch (get_entity_visibility(ent)) {
131       X(visibility_local);
132       X(visibility_external_visible);
133       X(visibility_external_allocated);
134     }
135
136     fprintf(F, "\n%s  variability: ", prefix);
137     switch (get_entity_variability(ent)) {
138       X(variability_uninitialized);
139       X(variability_initialized);
140       X(variability_part_constant);
141       X(variability_constant);
142     }
143     fprintf(F, "\n");
144   } else {  /* no entattrs */
145     fprintf(F, "%s(%3d) %*s: %s", prefix,
146             get_entity_offset_bits(ent), -40, get_type_name(get_entity_type(ent)), get_entity_name(ent));
147     if (is_method_type(get_entity_type(ent))) fprintf(F, "(...)");
148
149     if (verbosity & dump_verbosity_accessStats) {
150       if (get_entity_allocation(ent) == allocation_static) fprintf(F, " (stat)");
151       if (get_entity_peculiarity(ent) == peculiarity_description) fprintf(F, " (desc)");
152       if (get_entity_peculiarity(ent) == peculiarity_inherited)   fprintf(F, " (inh)");
153     }
154     fprintf(F, "\n");
155   }
156
157   if (verbosity & dump_verbosity_entconsts) {
158     if (get_entity_variability(ent) != variability_uninitialized) {
159       if (is_atomic_entity(ent)) {
160         fprintf(F, "%s  atomic value: ", prefix);
161         dump_node_opcode(F, get_atomic_ent_value(ent));
162       } else {
163         fprintf(F, "%s  compound values:", prefix);
164         for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
165           compound_graph_path *path = get_compound_ent_value_path(ent, i);
166           entity *ent0 = get_compound_graph_path_node(path, 0);
167           fprintf(F, "\n%s    %3d ", prefix, get_entity_offset_bits(ent0));
168           if (get_type_state(type) == layout_fixed)
169             fprintf(F, "(%3d) ",   get_compound_ent_value_offset_bits(ent, i));
170           fprintf(F, "%s", get_entity_name(ent0));
171           for (j = 0; j < get_compound_graph_path_length(path); ++j) {
172             entity *node = get_compound_graph_path_node(path, j);
173             fprintf(F, ".%s", get_entity_name(node));
174             if (is_array_type(get_entity_owner(node)))
175               fprintf(F, "[%d]", get_compound_graph_path_array_index(path, j));
176           }
177           fprintf(F, "\t = ");
178           dump_node_opcode(F, get_compound_ent_value(ent, i));
179         }
180       }
181       fprintf(F, "\n");
182     }
183   }
184
185   if (verbosity & dump_verbosity_entattrs) {
186     fprintf(F, "%s  volatility:  ", prefix);
187     switch (get_entity_volatility(ent)) {
188       X(volatility_non_volatile);
189       X(volatility_is_volatile);
190     }
191
192     fprintf(F, "\n%s  peculiarity: %s", prefix, get_peculiarity_string(get_entity_peculiarity(ent)));
193     fprintf(F, "\n%s  ld_name: %s", prefix, ent->ld_name ? get_entity_ld_name(ent) : "no yet set");
194     fprintf(F, "\n%s  offset:  %d", prefix, get_entity_offset_bits(ent));
195     if (is_method_type(get_entity_type(ent))) {
196       if (get_entity_irg(ent))   /* can be null */ {
197         fprintf(F, "\n%s  irg = %ld", prefix, get_irg_graph_nr(get_entity_irg(ent)));
198         if (get_irp_callgraph_state() == irp_callgraph_and_calltree_consistent) {
199           fprintf(F, "\n%s    recursion depth %d", prefix, get_irg_recursion_depth(get_entity_irg(ent)));
200           fprintf(F, "\n%s    loop depth      %d", prefix, get_irg_loop_depth(get_entity_irg(ent)));
201         }
202       } else {
203         fprintf(F, "\n%s  irg = NULL", prefix);
204       }
205     }
206     fprintf(F, "\n");
207   }
208
209   if (verbosity & dump_verbosity_accessStats) {
210     int n_acc = get_entity_n_accesses(ent);
211     int L_freq[MY_SIZE];
212     int max_L_freq = -1;
213     int S_freq[MY_SIZE];
214     int max_S_freq = -1;
215     int LA_freq[MY_SIZE];
216     int max_LA_freq = -1;
217     int SA_freq[MY_SIZE];
218     int max_SA_freq = -1;
219     for (i = 0; i < MY_SIZE; ++i) {
220       L_freq[i] = 0;
221       LA_freq[i] = 0;
222       S_freq[i] = 0;
223       SA_freq[i] = 0;
224     }
225
226     for (i = 0; i < n_acc; ++i) {
227       ir_node *acc = get_entity_access(ent, i);
228       int depth = get_weighted_loop_depth(acc);
229       assert(depth < MY_SIZE);
230       if ((get_irn_op(acc) == op_Load) || (get_irn_op(acc) == op_Call)) {
231         L_freq[depth]++;
232         max_L_freq = (depth > max_L_freq) ? depth : max_L_freq;
233         if (addr_is_alloc(acc)) {
234           LA_freq[depth]++;
235           max_LA_freq = (depth > max_LA_freq) ? depth : max_LA_freq;
236         }
237       } else if (get_irn_op(acc) == op_Store) {
238         S_freq[depth]++;
239         max_S_freq = (depth > max_S_freq) ? depth : max_S_freq;
240         if (addr_is_alloc(acc)) {
241           SA_freq[depth]++;
242           max_SA_freq = (depth > max_SA_freq) ? depth : max_SA_freq;
243         }
244       } else {
245         assert(0);
246       }
247     }
248
249     if (max_L_freq >= 0) {
250       fprintf(F, "%s  Load  Stats", prefix);
251       char comma = ':';
252       for (i = 0; i <= max_L_freq; ++i) {
253         if (L_freq[i])
254           fprintf(F, "%c %d x  L%d", comma, L_freq[i], i);
255         else
256           fprintf(F, "         ");
257         comma = ',';
258       }
259       fprintf(F, "\n");
260     }
261     if (max_LA_freq >= 0) {
262       //fprintf(F, "%s  LoadA Stats", prefix);
263       char comma = ':';
264       for (i = 0; i <= max_LA_freq; ++i) {
265         //if (LA_freq[i])
266           //fprintf(F, "%c %d x LA%d", comma, LA_freq[i], i);
267           //else
268           //fprintf(F, "         ");
269         comma = ',';
270       }
271       fprintf(F, "\n");
272     }
273     if (max_S_freq >= 0) {
274       fprintf(F, "%s  Store Stats", prefix);
275       char comma = ':';
276       for (i = 0; i <= max_S_freq; ++i) {
277         if (S_freq[i])
278           fprintf(F, "%c %d x  S%d", comma, S_freq[i], i);
279         else
280           fprintf(F, "         ");
281         comma = ',';
282       }
283       fprintf(F, "\n");
284     }
285     if (max_SA_freq >= 0) {
286       //fprintf(F, "%s  StoreAStats", prefix);
287       char comma = ':';
288       for (i = 0; i <= max_SA_freq; ++i) {
289         //if (SA_freq[i])
290           //fprintf(F, "%c %d x SA%d", comma, SA_freq[i], i);
291         //else
292           //fprintf(F, "         ");
293         comma = ',';
294       }
295       fprintf(F, "\n");
296     }
297   }
298
299 }
300 #undef X
301
302 void    dump_entity_to_file (FILE *F, entity *ent, unsigned verbosity) {
303   dump_entity_to_file_prefix (F, ent, "", verbosity);
304   fprintf(F, "\n");
305 }
306
307 void dump_entity (entity *ent) {
308   dump_entity_to_file(stdout, ent, dump_verbosity_max);
309 }
310
311 void    dump_entitycsv_to_file_prefix (FILE *F, entity *ent, char *prefix, unsigned verbosity,
312                                        int *max_disp, int disp[], const char *comma) {
313   int i;
314   int n_acc = get_entity_n_accesses(ent);
315   int L_freq[MY_SIZE];
316   int max_L_freq = -1;
317   int S_freq[MY_SIZE];
318   int max_S_freq = -1;
319   int LA_freq[MY_SIZE];
320   int max_LA_freq = -1;
321   int SA_freq[MY_SIZE];
322   int max_SA_freq = -1;
323   for (i = 0; i < MY_SIZE; ++i) {
324     L_freq[i] = 0;
325     LA_freq[i] = 0;
326     S_freq[i] = 0;
327     SA_freq[i] = 0;
328   }
329
330   for (i = 0; i < n_acc; ++i) {
331     ir_node *acc = get_entity_access(ent, i);
332     int depth = get_weighted_loop_depth(acc);
333     assert(depth < MY_SIZE);
334     if ((get_irn_op(acc) == op_Load) || (get_irn_op(acc) == op_Call)) {
335       L_freq[depth]++;
336       max_L_freq = (depth > max_L_freq) ? depth : max_L_freq;
337       if (addr_is_alloc(acc)) {
338         LA_freq[depth]++;
339         max_LA_freq = (depth > max_LA_freq) ? depth : max_LA_freq;
340       }
341       if (get_entity_allocation(ent) == allocation_static) {
342         disp[depth]++;
343         *max_disp = (depth > *max_disp) ? depth : *max_disp;
344       }
345     } else if (get_irn_op(acc) == op_Store) {
346       S_freq[depth]++;
347       max_S_freq = (depth > max_S_freq) ? depth : max_S_freq;
348       if (addr_is_alloc(acc)) {
349         SA_freq[depth]++;
350         max_SA_freq = (depth > max_SA_freq) ? depth : max_SA_freq;
351       }
352       if (get_entity_allocation(ent) == allocation_static) {
353         assert(0);
354       }
355     } else {
356       assert(0);
357     }
358   }
359
360   if (get_entity_allocation(ent) == allocation_static) return;
361
362   fprintf(F, "%s_%s", get_type_name(get_entity_owner(ent)), get_entity_name(ent));
363
364   if (max_L_freq >= 0) {
365     fprintf(F, "%s Load", comma);
366     for (i = 0; i <= max_L_freq; ++i) {
367       fprintf(F, "%s %d", comma, L_freq[i]);
368     }
369   }
370   if (max_S_freq >= 0) {
371     if (max_L_freq >= 0)    fprintf(F, "\n%s_%s", get_type_name(get_entity_owner(ent)), get_entity_name(ent));
372     fprintf(F, "%s Store", comma);
373     for (i = 0; i <= max_S_freq; ++i) {
374       fprintf(F, "%s %d", comma, S_freq[i]);
375     }
376   }
377   fprintf(F, "\n");
378 }
379
380 /* A fast hack to dump a csv. */
381 void dump_typecsv_to_file(FILE *F, type *tp, dump_verbosity verbosity, const char *comma) {
382   if (!is_class_type(tp)) return;
383
384   if (verbosity & dump_verbosity_accessStats) {
385     int i, n_all = get_type_n_allocations(tp);
386     int freq[MY_SIZE];
387     int max_freq = -1;
388     int disp[MY_SIZE];   /* Accumulated accesses to static members: dispatch table. */
389     int max_disp = -1;
390     for (i = 0; i < MY_SIZE; ++i) {
391       freq[i] = 0;
392       disp[i] = 0;
393     }
394
395     for (i = 0; i < n_all; ++i) {
396       ir_node *all = get_type_allocation(tp, i);
397       int depth = get_weighted_loop_depth(all);
398       assert(depth < MY_SIZE);
399       freq[depth]++;
400       max_freq = (depth > max_freq) ? depth : max_freq;
401       assert(get_irn_op(all) == op_Alloc);
402     }
403
404     fprintf(F, "%s ", get_type_name(tp));
405     fprintf(F, "%s Alloc ", comma);
406
407     if (max_freq >= 0) {
408       for (i = 0; i <= max_freq; ++i) {
409         fprintf(F, "%s %d", comma, freq[i]);
410       }
411     }
412     fprintf(F, "\n");
413
414     for (i = 0; i < get_class_n_members(tp); ++i) {
415       entity *mem = get_class_member(tp, i);
416       if (((verbosity & dump_verbosity_methods) &&  is_method_type(get_entity_type(mem))) ||
417           ((verbosity & dump_verbosity_fields)  && !is_method_type(get_entity_type(mem)))   ) {
418         dump_entitycsv_to_file_prefix(F, mem, "    ", verbosity, &max_disp, disp, comma);
419       }
420     }
421
422     if (max_disp >= 0) {
423       fprintf(F, "%s__disp_tab%s Load", get_type_name(tp), comma);
424       for (i = 0; i <= max_disp; ++i) {
425         fprintf(F, "%s %d", comma, disp[i]);
426       }
427       fprintf(F, "\n");
428     }
429   }
430 }
431
432 void dump_type_to_file (FILE *F, type *tp, dump_verbosity verbosity) {
433   int i;
434
435   if ((is_class_type(tp))       && (verbosity & dump_verbosity_noClassTypes)) return;
436   if ((is_struct_type(tp))      && (verbosity & dump_verbosity_noStructTypes)) return;
437   if ((is_union_type(tp))       && (verbosity & dump_verbosity_noUnionTypes)) return;
438   if ((is_array_type(tp))       && (verbosity & dump_verbosity_noArrayTypes)) return;
439   if ((is_pointer_type(tp))     && (verbosity & dump_verbosity_noPointerTypes)) return;
440   if ((is_method_type(tp))      && (verbosity & dump_verbosity_noMethodTypes)) return;
441   if ((is_primitive_type(tp))   && (verbosity & dump_verbosity_noPrimitiveTypes)) return;
442   if ((is_enumeration_type(tp)) && (verbosity & dump_verbosity_noEnumerationTypes)) return;
443
444   fprintf(F, "%s type %s (%ld)", get_tpop_name(get_type_tpop(tp)), get_type_name(tp), get_type_nr(tp));
445   if (verbosity & dump_verbosity_onlynames) { fprintf(F, "\n"); return; }
446
447   switch (get_type_tpop_code(tp)) {
448
449   case tpo_class:
450     if ((verbosity & dump_verbosity_methods) || (verbosity & dump_verbosity_fields)) {
451       fprintf(F, "\n  members: \n");
452     }
453     for (i = 0; i < get_class_n_members(tp); ++i) {
454       entity *mem = get_class_member(tp, i);
455       if (((verbosity & dump_verbosity_methods) &&  is_method_type(get_entity_type(mem))) ||
456           ((verbosity & dump_verbosity_fields)  && !is_method_type(get_entity_type(mem)))   ) {
457         dump_entity_to_file_prefix(F, mem, "    ", verbosity);
458       }
459     }
460     if (verbosity & dump_verbosity_typeattrs) {
461       fprintf(F, "  supertypes: ");
462       for (i = 0; i < get_class_n_supertypes(tp); ++i) {
463         type *stp = get_class_supertype(tp, i);
464         fprintf(F, "\n    %s", get_type_name(stp));
465       }
466       fprintf(F, "\n  subtypes: ");
467       for (i = 0; i < get_class_n_subtypes(tp); ++i) {
468         type *stp = get_class_subtype(tp, i);
469         fprintf(F, "\n    %s", get_type_name(stp));
470       }
471
472       fprintf(F, "\n  peculiarity: %s", get_peculiarity_string(get_class_peculiarity(tp)));
473     }
474     break;
475
476   case tpo_union:
477   case tpo_struct:
478     if (verbosity & dump_verbosity_fields) fprintf(F, "\n  members: ");
479     for (i = 0; i < get_compound_n_members(tp); ++i) {
480       entity *mem = get_compound_member(tp, i);
481       if (verbosity & dump_verbosity_fields) {
482         dump_entity_to_file_prefix(F, mem, "    ", verbosity);
483       }
484     }
485     break;
486
487   case tpo_pointer: {
488     if (verbosity & dump_verbosity_typeattrs) {
489       type *tt = get_pointer_points_to_type(tp);
490       fprintf(F, "\n  points to %s (%ld)", get_type_name(tt), get_type_nr(tt));
491     }
492
493   } break;
494
495   default:
496     if (verbosity & dump_verbosity_typeattrs) {
497       fprintf(F, ": details not implemented\n");
498     }
499   }
500
501   if (verbosity & dump_verbosity_accessStats) {
502     int n_all = get_type_n_allocations(tp);
503     int freq[MY_SIZE];
504     int max_freq = -1;
505     for (i = 0; i < MY_SIZE; ++i) freq[i] = 0;
506
507     for (i = 0; i < n_all; ++i) {
508       ir_node *all = get_type_allocation(tp, i);
509       int depth = get_weighted_loop_depth(all);
510       assert(depth < MY_SIZE);
511       freq[depth]++;
512       max_freq = (depth > max_freq) ? depth : max_freq;
513       assert(get_irn_op(all) == op_Alloc);
514     }
515
516     if (max_freq >= 0) {
517       fprintf(F, "  Alloc Stats");
518       char comma = ':';
519       for (i = 0; i <= max_freq; ++i) {
520         fprintf(F, "%c %d x A%d", comma, freq[i], i);
521         comma = ',';
522       }
523       fprintf(F, "\n");
524     }
525   }
526
527   fprintf(F, "\n\n");
528 }
529
530 void dump_type(type *tp) {
531   dump_type_to_file (stdout, tp, dump_verbosity_max);
532 }
533
534 /* Just opens a file, mangling a file name.
535  *
536  * The name consists of the following parts:
537  *
538  * @arg basename  The basis of the name telling about the content.
539  * @arg
540  *
541  */
542
543 static FILE *text_open (const char *basename, const char * suffix1, const char *suffix2, const char *suffix3) {
544   FILE *F;
545   int len = strlen(basename), i, j;
546   char *fname;  /* filename to put the vcg information in */
547
548   if (!basename) assert(basename);
549   if (!suffix1) suffix1 = "";
550   if (!suffix2) suffix2 = "";
551   if (!suffix3) suffix3 = ".txt";
552
553   /* open file for vcg graph */
554   fname = malloc (strlen(basename)*2 + strlen(suffix1) + strlen(suffix2) + 5); /* *2: space for excapes. */
555
556   j = 0;
557   for (i = 0; i < len; ++i) {  /* replase '/' in the name: escape by @. */
558     if (basename[i] == '/') {
559       fname[j] = '@'; j++; fname[j] = '1'; j++;
560     } else if (basename[i] == '@') {
561       fname[j] = '@'; j++; fname[j] = '2'; j++;
562     } else {
563       fname[j] = basename[i]; j++;
564     }
565   }
566   fname[j] = '\0';
567   strcat (fname, suffix1);  /* append file suffix */
568   strcat (fname, suffix2);  /* append file suffix */
569   strcat (fname, suffix3);  /* append the .txt suffix */
570
571   F = fopen (fname, "w");   /* open file for writing */
572   if (!F) {
573     assert(0);
574   }
575   free(fname);
576
577   return F;
578 }
579
580 void dump_types_as_text(unsigned verbosity, const char *suffix) {
581   const char *basename;
582   FILE *F, *CSV;
583   int i, n_types = get_irp_n_types();
584
585   basename = irp_prog_name_is_set() ? get_irp_prog_name() : "TextTypes";
586   F = text_open (basename, suffix, "-types", ".txt");
587
588   if (verbosity & dump_verbosity_csv) {
589     CSV = text_open (basename, suffix, "-types", ".csv");
590     //fprintf(CSV, "Class, Field, Operation, L0, L1, L2, L3\n");
591   }
592
593   for (i = 0; i < n_types; ++i) {
594     type *t = get_irp_type(i);
595
596     if (is_jack_rts_class(t)) continue;
597
598     dump_type_to_file(F, t, verbosity);
599     if (verbosity & dump_verbosity_csv) {
600       dump_typecsv_to_file(CSV, t, verbosity, "");
601     }
602   }
603
604   fclose (F);
605   if (verbosity & dump_verbosity_csv) fclose (CSV);
606 }