pto_name.c
[libfirm] / ir / ana2 / pto_name.c
1 /* -*- c -*- */
2
3 /*
4   Project:     libFIRM
5   File name:   ir/ana/pto_name.c
6   Purpose:     Names for abstract objects
7   Author:      Florian
8   Modified by:
9   Created:     Sat Nov 13 19:35:27 CET 2004
10   CVS-ID:      $Id$
11   Copyright:   (c) 1999-2004 Universität Karlsruhe
12   Licence:     This file is protected by the GPL -  GNU GENERAL PUBLIC LICENSE.
13 */
14
15 # ifdef HAVE_CONFIG_H
16 #  include "config.h"
17 # endif
18
19 /*
20   pto_name: Names for abstract objects
21 */
22
23 # include "pto.h"
24 # include "pto_name.h"
25 # include "pto_util.h"
26
27 # include <string.h>            /* for memcpy */
28 # include <obstack.h>
29 # include <errno.h>
30
31 # include "irnode.h"
32 # include "irprog.h"
33 # include "xmalloc.h"
34
35 # include "pto_debug.h"
36
37 /* Local Defines: */
38 # define obstack_chunk_alloc xmalloc
39 # define obstack_chunk_free free
40
41 # define NALLOC(size)   obstack_alloc (name_obst, size)
42
43 /* Local Data Types: */
44
45 /* Local Variables: */
46 struct obstack *qset_obst = NULL;
47 struct obstack *name_obst = NULL;
48
49 static desc_t *all_descs = NULL;
50
51 static int name_id = 0;
52
53 # define PTO_COLOR
54
55 # ifdef PTO_COLOR
56 static int last_col_idx = 0;
57
58 /* Local Prototypes: */
59 static int pto_name_alloc_color (desc_t*);
60 static void pto_name_set_color (desc_t*, int);
61 # endif /* defined PTO_COLOR */
62
63 /* ===================================================
64    Local Implementation:
65    =================================================== */
66 # ifdef PTO_COLOR
67 /* set a nice color to an object descriptor */
68 static void pto_name_set_obj_color (obj_desc_t *obj_desc, int col_idx)
69 {
70   int i;
71
72   for (i = 0; i < obj_desc->n_fields; i ++) {
73     qset_t *ptos = obj_desc->values [i];
74
75     desc_t *tgt = (desc_t*) qset_start (ptos);
76
77     while (NULL != tgt) {
78       pto_name_set_color (tgt, col_idx);
79
80       tgt = (desc_t*) qset_next (ptos);
81     }
82   }
83 }
84
85 /* set a nice color to an array descriptor */
86 static void pto_name_set_arr_color (arr_desc_t *arr_desc, int col_idx)
87 {
88   qset_t *ptos = arr_desc->value;
89
90   desc_t *tgt = (desc_t*) qset_start (ptos);
91
92   while (NULL != tgt) {
93     pto_name_set_color (tgt, col_idx);
94
95     tgt = (desc_t*) qset_next (ptos);
96   }
97 }
98
99 /* set a nice color to a descriptor */
100 static void pto_name_set_color (desc_t *desc, int col_idx)
101 {
102   /* assert (0 == desc->col_idx); */
103
104   desc->col_idx = col_idx;
105
106   if (FALSE == desc->visit) {
107     desc->visit = TRUE;
108     if (object == desc->kind) {
109       pto_name_set_obj_color ((obj_desc_t*) desc, col_idx);
110     } else if (array == desc->kind) {
111       pto_name_set_arr_color ((arr_desc_t*) desc, col_idx);
112     }
113
114     desc->visit = FALSE;
115   }
116 }
117
118
119 /* allocate nice colors for an object descriptor */
120 static int pto_name_alloc_obj_color (obj_desc_t *obj_desc)
121 {
122   int i;
123   int col_idx = 0;
124
125   for (i = 0; (0 == col_idx) && (i < obj_desc->n_fields); i ++) {
126     qset_t *ptos = obj_desc->values [i];
127     desc_t *tgt = (desc_t*) qset_start (ptos);
128
129     while ((0 == col_idx) && (NULL != tgt)) {
130       col_idx = pto_name_alloc_color (tgt);
131
132       tgt = (desc_t*) qset_next (ptos);
133     }
134   }
135
136   return (col_idx);
137 }
138
139 /* allocate nice colors for an array descriptor */
140 static int pto_name_alloc_arr_color (arr_desc_t *arr_desc)
141 {
142   int col_idx = 0;
143
144   qset_t *ptos = arr_desc->value;
145
146   desc_t *tgt = (desc_t*) qset_start (ptos);
147
148   while ((NULL != tgt) && (0 == col_idx)) {
149     col_idx = pto_name_alloc_color (tgt);
150     tgt = (desc_t*) qset_next (ptos);
151   }
152
153   return (col_idx);
154 }
155
156 /* allocate nice colors for the given descriptor */
157 static int pto_name_alloc_color (desc_t *desc)
158 {
159   if (0 != desc->col_idx) {
160     return (desc->col_idx);
161   }
162
163   int col_idx = 0;
164
165   if (FALSE == desc->visit) {
166     desc->visit = TRUE;
167     if (object == desc->kind) {
168       col_idx = pto_name_alloc_obj_color ((obj_desc_t*) desc);
169     } else if (array == desc->kind) {
170       col_idx = pto_name_alloc_arr_color ((arr_desc_t*) desc);
171     }
172     desc->visit = FALSE;
173   }
174
175   if (0 == col_idx) {
176     col_idx = ++ last_col_idx;
177   }
178
179   pto_name_set_color (desc, col_idx);
180
181   return (col_idx);
182 }
183
184 /* allocate nice colors */
185 static void pto_name_alloc_colors (void)
186 {
187   desc_t *desc = all_descs;
188
189   while (NULL != desc) {
190     pto_name_alloc_color (desc);
191
192     desc = desc->prev;
193   }
194 }
195 # endif /* defined PTO_COLOR */
196
197 /* See whether the given entity is a field. */
198 static int is_field (entity *ent)
199 {
200   type *tp = get_entity_type (ent);
201
202   if (is_primitive_type (tp) || is_pointer_type (tp)) {
203     /* actually, we don't get by by restricting ourselves to pointer types */
204     return (TRUE);
205   } else {
206     return (FALSE);
207   }
208 }
209
210 /* Helper to collect_fields(type*): collect all fields of the given
211   clazz and its super classes into the given obstack. */
212 static void _collect_fields (type *clazz, struct obstack *obst)
213 {
214   int n_members = get_class_n_members (clazz);
215   int n_supers  = get_class_n_supertypes (clazz);
216   int i;
217
218   for (i = 0; i < n_members; i ++) {
219     entity *ent = get_class_member (clazz, i);
220
221     if (is_field (ent)) {
222       if (allocation_static != get_entity_allocation (ent)) {
223         obstack_ptr_grow (obst, ent);
224       }
225     }
226   }
227
228   for (i = 0; i < n_supers; i ++) {
229     type *s_clazz = get_class_supertype (clazz, i);
230
231     _collect_fields (s_clazz, obst);
232   }
233 }
234
235 /* Collect the fields of the given class and its super classes into an array.
236   The last entry of the array is written NULL. */
237 static entity **collect_fields (type *clazz)
238 {
239   if (NULL != get_type_link (clazz)) {
240     DBGPRINT (3, (stdout, "%s: reusing field list for \"%s\"\n",
241                   __FUNCTION__, get_type_name (clazz)));
242
243     return ((entity **) get_type_link (clazz));
244   } else {
245     DBGPRINT (2, (stdout, "%s: new field list for \"%s\"\n",
246                   __FUNCTION__, get_type_name (clazz)));
247   }
248
249   struct obstack obst;
250
251   obstack_init (&obst);
252
253   _collect_fields (clazz, &obst);
254
255   /* append terminating NULL */
256   int *the_null = NULL;
257   obstack_ptr_grow (&obst, the_null);
258
259   int n_fields = obstack_object_size (&obst) / sizeof (void*);
260
261   entity ** fields = (entity**) NALLOC (n_fields * sizeof (entity*));
262   void *tmp = obstack_finish (&obst);
263
264   memcpy (fields, tmp, n_fields * sizeof (entity*));
265
266   obstack_free (&obst, NULL);
267
268   set_type_link (clazz, (void*) fields);
269
270   return (fields);
271 }
272
273 /* Write the intro text for a name dump into the given stream */
274 static void pto_name_dump_start (FILE *stream)
275 {
276 # ifdef PTO_COLOR
277   pto_name_alloc_colors ();
278 # endif /* defined PTO_COLOR */
279
280   fprintf (stream, "digraph \"Names\" {\n");
281   fprintf (stream, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11,7\", rotate=\"90\"];\n");
282   fprintf (stream, "\tnode [shape=\"record\", style=\"filled\"];\n");
283   fprintf (stream, "\tedge [color=\"black\"];\n");
284   fprintf (stream, "\n");
285 }
286
287 /* Write the extro text for a name dump into the given stream */
288 static void pto_name_dump_finish (FILE *stream)
289 {
290   fprintf (stream, "}\n");
291 }
292
293 /* Write a node for the given descriptor into the given stream */
294 static void pto_name_dump_desc (desc_t *desc, FILE *stream)
295 {
296   type *tp = desc->tp;
297   const char *tp_name = get_type_name (tp);
298
299   fprintf (stream, "\t/* %s \"%s\" */\n",
300            object == desc->kind ? "Object" : "Array",
301            tp_name);
302
303   fprintf (stream, "\tdesc_%i [label=\"<HEAD>type \\[%i\\]\\lname=\\\"%s\\\"",
304            desc->id,
305            desc->id,
306            tp_name);
307
308   ir_node *nd = desc->node;
309
310   if (NULL != nd) {
311     ir_graph *graph = get_irn_irg (nd);
312     entity *method = get_irg_entity (graph);
313     const char *ent_name = get_entity_name (method);
314     const char *own_name = get_type_name (get_entity_owner (method));
315
316     fprintf (stream, "\\lnode=%s\\[%li\\]",
317              get_op_name (get_irn_op (nd)),
318              get_irn_node_nr (nd));
319     fprintf (stream, "\\lgraph=\\\"%s.%s\\\"",
320              own_name,
321              ent_name);
322   }
323
324   if (desc->kind == object) {
325     obj_desc_t *obj_desc = (obj_desc_t*) desc;
326
327     int i;
328     for (i = 0; i < obj_desc->n_fields; i ++) {
329       entity *field = obj_desc->fields [i];
330
331       if (is_pointer_type (get_entity_type (field))) {
332         const char *ent_name = get_entity_name (field);
333
334         fprintf (stream, "|<%i>%s", i, ent_name);
335       }
336     }
337   } else if (array == desc->kind) {
338     fprintf (stream, "|<arr>[]");
339   } else {
340     assert (0 && "invalid descriptor");
341   }
342
343   /* end label string */
344   fprintf (stream, "\"");
345
346 # ifdef PTO_COLOR
347   int col_idx = desc->col_idx;
348   float hue = (float) col_idx / (float) last_col_idx;
349   float sat = 1.000;            /* 0.300 .. 1.000 */
350   float val = 0.800;            /* 0.300 .. 1.000 */
351
352 # define MAX_COLORS 12
353   if (last_col_idx > MAX_COLORS) {
354     /* too many colors ... vary value too */
355     float div = (float) MAX_COLORS / (float) last_col_idx;
356
357     sat = (div * ((col_idx / MAX_COLORS)));
358     val = (div * ((col_idx / MAX_COLORS)));
359
360     col_idx = col_idx % MAX_COLORS;
361     hue = (float) col_idx / (float) MAX_COLORS;
362
363     // re-adjust sat and val
364     {
365       const float sat_min = 0.200; /* 0.200 .. 0.400 */
366       const float val_min = 0.300; /* 0.300 .. 0.400 */
367
368       sat = sat_min + ((1.0 - sat_min) * sat);
369       val = val_min + ((1.0 - val_min) * val);
370     }
371   }
372 # undef MAX_COLORS
373
374   fprintf (stream, ", color=\"%01.3f, %01.3f, %01.3f\"", hue, sat, val);
375
376   char *fontcolor;
377
378   if ((hue > 0.3) && (sat < 0.5)) {
379     fontcolor = "white";
380   } else if (sat < 0.4) {
381     fontcolor = "white";
382   } else {
383     fontcolor = "black";
384   }
385
386   fprintf (stream, ", fontcolor=\"%s\"", fontcolor);
387 # else /* if defined PTO_COLOR */
388   fprintf (stream, ", color=\"lightgrey\"");
389 # endif /* defined PTO_COLOR */
390
391   /* end attributes */
392   fprintf (stream, "];\n");
393   fprintf (stream, "\n");
394
395   /* now the edges */
396   if (desc->kind == object) {
397     obj_desc_t *obj_desc = (obj_desc_t*) desc;
398
399     int i;
400     for (i = 0; i < obj_desc->n_fields; i ++) {
401       desc_t *tgt = (desc_t*) qset_start (obj_desc->values [i]);
402
403       while (NULL != tgt) {
404         fprintf (stream, "\tdesc_%i:%i -> desc_%i:HEAD;\n",
405                  desc->id, i, tgt->id);
406
407         tgt = (desc_t*) qset_next (obj_desc->values [i]);
408       }
409     }
410   } else if (array == desc->kind) {
411     arr_desc_t *arr_desc = (arr_desc_t*) desc;
412
413     desc_t *tgt = (desc_t*) qset_start (arr_desc->value);
414
415     while (NULL != tgt) {
416       fprintf (stream, "\tdesc_%i:arr -> desc_%i:HEAD;\n",
417                desc->id, tgt->id);
418
419       tgt = (desc_t*) qset_next (arr_desc->value);
420     }
421   }
422
423   fprintf (stream, "\n");
424 }
425
426
427 /* ===================================================
428    Exported Implementation:
429    =================================================== */
430 /* Find the given descriptor's entry for the given entity */
431 qset_t *get_entry (desc_t *desc, entity *ent)
432 {
433
434   if (desc->kind == object) {
435     obj_desc_t *obj_desc = (obj_desc_t*) desc;
436     int i;
437     const int n_fields = obj_desc->n_fields;
438
439     for (i = 0; i < n_fields; i ++) {
440       if (ent == obj_desc->fields [i]) {
441         return (obj_desc->values [i]);
442       }
443     }
444
445     assert (0 && "entry not found");
446   } else if (desc->kind == array) {
447     arr_desc_t *arr_desc = (arr_desc_t*) desc;
448
449     return (arr_desc->value);
450   } else {
451     assert (0 && "invalid descriptor");
452   }
453 }
454
455
456 /* get a new descriptor for the given type at the given node */
457 desc_t *new_name (type *tp, ir_node *node)
458 {
459   desc_t *desc = NULL;
460
461   assert ((is_class_type (tp) || is_array_type (tp)) && "unsuitable type");
462
463   DBGPRINT (2, (stdout, "%s: new name for type \"%s\"\n", __FUNCTION__,
464                 get_type_name (tp)));
465   fflush (stdout);
466
467   if (is_class_type (tp)) {
468     obj_desc_t *obj_desc = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
469     int i;
470     int n_fields;
471
472     obj_desc->kind = object;
473     obj_desc->fields = collect_fields (tp);
474
475     for (n_fields = 0; (NULL != obj_desc->fields [n_fields]); n_fields ++) {
476       /* nothing, just count ... */
477     }
478
479     obj_desc->n_fields = n_fields;
480     obj_desc->values = (qset_t**) NALLOC (n_fields * sizeof (qset_t));
481
482     for (i = 0; i < n_fields; i ++) {
483       obj_desc->values [i] = qset_new (N_INITIAL_OJBS, qset_obst);
484     }
485
486     desc = (desc_t*) obj_desc;
487   } else if (is_array_type (tp)) {
488     arr_desc_t *arr_desc = (arr_desc_t*) NALLOC (sizeof (arr_desc_t));
489
490     arr_desc->kind = array;
491     arr_desc->value = qset_new (N_INITIAL_OJBS, qset_obst);
492
493     desc = (desc_t*) arr_desc;
494   }
495
496   desc->id   = name_id ++;
497   desc->col_idx = 0;
498   desc->tp   = tp;
499   desc->visit = FALSE;
500   desc->node = node;
501
502   desc->prev = all_descs;
503   all_descs = desc;
504
505   return (desc);
506 }
507
508 # define N_GLOB_INITIAL_FIELDS  20
509 static obj_desc_t *obj_glob = NULL;
510 static int n_glob_fields = N_GLOB_INITIAL_FIELDS;
511
512 /* get a new descriptor for the given (presumably static) entity */
513 desc_t *new_ent_name (entity *ent)
514 {
515   int i;
516   int missing = TRUE;
517   type *tp = get_entity_type (ent);
518
519   assert (is_pointer_type (tp));
520   tp = get_pointer_points_to_type (tp);
521   assert (is_class_type (tp));
522
523   DBGPRINT (2, (stdout, "%s: new name for entity \"%s\"\n", __FUNCTION__,
524                 get_entity_name (ent)));
525   DBGEXE (fflush (stdout));
526
527   assert (((allocation_static == get_entity_allocation (ent)) ||
528            (allocation_automatic == get_entity_allocation (ent))) &&
529           "not a static/automatic field");
530
531   if (NULL == obj_glob) {
532     obj_glob = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
533
534     obj_glob->id   = name_id ++;
535     obj_glob->col_idx = 0;
536     obj_glob->visit = FALSE;
537     obj_glob->kind = object;
538     obj_glob->tp   = get_glob_type ();
539     obj_glob->node = NULL;
540
541     obj_glob->n_fields = 0;
542     obj_glob->fields = (entity**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (entity*));
543     obj_glob->values = (qset_t**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (qset_t*));
544
545     obj_glob->prev = all_descs;
546     all_descs = (desc_t*) obj_glob;
547   }
548
549   for (i = 0; missing && (i < obj_glob->n_fields); i ++) {
550     if (ent == obj_glob->fields [i]) {
551       missing = FALSE;
552     }
553   }
554
555   if (missing) {
556     if (obj_glob->n_fields == n_glob_fields) {
557       entity **fields = obj_glob->fields;
558       qset_t **values = obj_glob->values;
559
560       n_glob_fields *= 2;
561       obj_glob->fields = (entity**) NALLOC (n_glob_fields * sizeof (entity*));
562       obj_glob->values = (qset_t**) NALLOC (n_glob_fields * sizeof (qset_t*));
563
564       memcpy (obj_glob->fields, fields, obj_glob->n_fields * sizeof (entity*));
565       memcpy (obj_glob->values, values, obj_glob->n_fields * sizeof (qset_t*));
566
567       /* free (fields); */
568       /* free (values); */
569     }
570
571     obj_glob->fields [obj_glob->n_fields   ] = ent;
572     obj_glob->values [obj_glob->n_fields ++] = qset_new (N_INITIAL_OJBS, qset_obst);
573   }
574
575   return ((desc_t*) obj_glob);
576 }
577 # undef N_GLOB_INITIAL_FIELDS
578
579 /* Dump all names to a file of the given name */
580 void pto_dump_names (const char *name)
581 {
582   desc_t *desc = all_descs;
583   FILE *stream = fopen (name, "w");
584
585   errno = 0;
586   if  (NULL == stream) {
587     fprintf (stderr, "%s: unable to open %s (%s)\n",
588              __FUNCTION__, name, strerror (errno));
589     return;
590   }
591
592   pto_name_dump_start (stream);
593
594   while (NULL != desc) {
595     pto_name_dump_desc (desc, stream);
596
597     desc = desc->prev;
598   }
599
600   pto_name_dump_finish (stream);
601   fclose (stream);
602 }
603
604 /* Initialise the name module */
605 void pto_name_init ()
606 {
607   DBGPRINT (3, (stdout, "(%s:%i) %s\n", __FILE__, __LINE__, __FUNCTION__));
608   assert (NULL == name_obst);
609   assert (NULL == qset_obst);
610
611   name_obst = xmalloc (sizeof (struct obstack));
612   qset_obst = xmalloc (sizeof (struct obstack));
613
614   obstack_init (name_obst);
615   obstack_init (qset_obst);
616 }
617
618 /* Cleanup the name module */
619 void pto_name_cleanup ()
620 {
621   DBGPRINT (3, (stdout, "(%s:%i) %s\n", __FILE__, __LINE__, __FUNCTION__));
622   obstack_free (name_obst, NULL);
623   obstack_free (qset_obst, NULL);
624
625   memset (name_obst, 0x00, sizeof (struct obstack));
626   memset (qset_obst, 0x00, sizeof (struct obstack));
627
628   free (name_obst);
629   free (qset_obst);
630
631   name_obst = NULL;
632   qset_obst = NULL;
633 }
634
635 \f
636 /*
637   $Log$
638   Revision 1.7  2004/12/15 09:18:18  liekweg
639   pto_name.c
640
641   Revision 1.6  2004/12/06 12:52:09  liekweg
642   colorize name dump
643
644   Revision 1.4  2004/11/30 15:49:27  liekweg
645   include 'dump'
646
647   Revision 1.3  2004/11/30 14:47:54  liekweg
648   fix initialisation; do correct iteration
649
650   Revision 1.2  2004/11/24 14:53:56  liekweg
651   Bugfixes
652
653   Revision 1.1  2004/11/18 16:37:34  liekweg
654   rewritten
655
656
657 */