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