Don't cast malloc
[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   int col_idx = 0;
160
161   if (0 != desc->col_idx) {
162     return (desc->col_idx);
163   }
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   struct obstack obst;
240   int n_fields;
241   entity ** fields;
242   void *tmp;
243
244   if (NULL != get_type_link (clazz)) {
245     DBGPRINT (3, (stdout, "collect_fields(): reusing field list for \"%s\"\n",
246                   get_type_name (clazz)));
247
248     return ((entity **) get_type_link (clazz));
249   } else {
250     DBGPRINT (2, (stdout, "collect_fields(): new field list for \"%s\"\n",
251                   get_type_name (clazz)));
252   }
253
254   obstack_init (&obst);
255
256   _collect_fields (clazz, &obst);
257
258   /* append terminating NULL */
259   obstack_ptr_grow (&obst, NULL);
260
261   n_fields = obstack_object_size (&obst) / sizeof (void*);
262
263   fields = NALLOC(n_fields * sizeof(*fields));
264   tmp = obstack_finish(&obst);
265
266   memcpy (fields, tmp, n_fields * sizeof(*fields));
267
268   obstack_free (&obst, NULL);
269
270   set_type_link (clazz, fields);
271
272   return (fields);
273 }
274
275 /* Write the intro text for a name dump into the given stream */
276 static void pto_name_dump_start (FILE *stream)
277 {
278 # ifdef PTO_COLOR
279   pto_name_alloc_colors ();
280 # endif /* defined PTO_COLOR */
281
282   fprintf (stream, "digraph \"Names\" {\n");
283   fprintf (stream, "\tgraph [rankdir=\"LR\", ordering=\"out\", size=\"11,7\", rotate=\"90\"];\n");
284   fprintf (stream, "\tnode [shape=\"record\", style=\"filled\"];\n");
285   fprintf (stream, "\tedge [color=\"black\"];\n");
286   fprintf (stream, "\n");
287 }
288
289 /* Write the extro text for a name dump into the given stream */
290 static void pto_name_dump_finish (FILE *stream)
291 {
292   fprintf (stream, "}\n");
293 }
294
295 /* Write a node for the given descriptor into the given stream */
296 static void pto_name_dump_desc (desc_t *desc, FILE *stream)
297 {
298   type *tp = desc->tp;
299   const char *tp_name = get_type_name (tp);
300   ir_node *nd;
301
302   fprintf (stream, "\t/* %s \"%s\" */\n",
303            object == desc->kind ? "Object" : "Array",
304            tp_name);
305
306   fprintf (stream, "\tdesc_%i [label=\"<HEAD>type \\[%i\\]",
307            desc->id, desc->id);
308
309   if (-1 != desc->ctx) {
310     fprintf (stream, ", ctx = %i", desc->ctx);
311   } else {
312     fprintf (stream, " (global)");
313   }
314
315   fprintf (stream, "\\lname=\\\"%s\\\"",
316            tp_name);
317
318   nd = desc->node;
319
320   if (NULL != nd) {
321     ir_graph *graph = get_irn_irg (nd);
322     entity *method = get_irg_entity (graph);
323     const char *ent_name = get_entity_name (method);
324     const char *own_name = get_type_name (get_entity_owner (method));
325
326     fprintf (stream, "\\lnode=%s\\[%li\\]",
327              get_op_name (get_irn_op (nd)),
328              get_irn_node_nr (nd));
329     fprintf (stream, "\\lgraph=\\\"%s.%s\\\"",
330              own_name,
331              ent_name);
332   }
333
334   if (desc->kind == object) {
335     obj_desc_t *obj_desc = (obj_desc_t*) desc;
336
337     int i;
338     for (i = 0; i < obj_desc->n_fields; i ++) {
339       entity *field = obj_desc->fields [i];
340
341       if (is_Pointer_type (get_entity_type (field))) {
342         const char *ent_name = get_entity_name (field);
343
344         fprintf (stream, "|<%i>%s", i, ent_name);
345       }
346     }
347   } else if (array == desc->kind) {
348     fprintf (stream, "|<arr>[]");
349   } else {
350     assert (0 && "invalid descriptor");
351   }
352
353   /* end label string */
354   fprintf (stream, "\"");
355
356 # ifdef PTO_COLOR
357   {
358     const char *fontcolor;
359     int col_idx = desc->col_idx;
360     float hue = (float) col_idx / (float) last_col_idx;
361     float sat = 1.000f;            /* 0.300 .. 1.000 */
362     float val = 0.800f;            /* 0.300 .. 1.000 */
363
364   # define MAX_COLORS 12
365     if (last_col_idx > MAX_COLORS) {
366       /* too many colors ... vary value too */
367       float div = (float) MAX_COLORS / (float) last_col_idx;
368
369       sat = (div * ((col_idx / MAX_COLORS)));
370       val = (div * ((col_idx / MAX_COLORS)));
371
372       col_idx = col_idx % MAX_COLORS;
373       hue = (float) col_idx / (float) MAX_COLORS;
374
375       // re-adjust sat and val
376       {
377         const float sat_min = 0.200f; /* 0.200 .. 0.400 */
378         const float val_min = 0.300f; /* 0.300 .. 0.400 */
379
380         sat = sat_min + ((1.0f - sat_min) * sat);
381         val = val_min + ((1.0f - val_min) * val);
382       }
383     }
384   # undef MAX_COLORS
385
386     fprintf (stream, ", color=\"%01.3f, %01.3f, %01.3f\"", hue, sat, val);
387
388     if ((hue > 0.3) && (sat < 0.5)) {
389       fontcolor = "white";
390     } else if (sat < 0.4) {
391       fontcolor = "white";
392     } else {
393       fontcolor = "black";
394     }
395
396     fprintf (stream, ", fontcolor=\"%s\"", fontcolor);
397   }
398 # else /* if defined PTO_COLOR */
399   fprintf (stream, ", color=\"lightgrey\"");
400 # endif /* defined PTO_COLOR */
401
402   /* end attributes */
403   fprintf (stream, "];\n");
404   fprintf (stream, "\n");
405
406   /* now the edges */
407   if (desc->kind == object) {
408     obj_desc_t *obj_desc = (obj_desc_t*) desc;
409
410     int i;
411     for (i = 0; i < obj_desc->n_fields; i ++) {
412       desc_t *tgt = (desc_t*) qset_start (obj_desc->values [i]);
413
414       while (NULL != tgt) {
415         fprintf (stream, "\tdesc_%i:%i -> desc_%i:HEAD;\n",
416                  desc->id, i, tgt->id);
417
418         tgt = (desc_t*) qset_next (obj_desc->values [i]);
419       }
420     }
421   } else if (array == desc->kind) {
422     arr_desc_t *arr_desc = (arr_desc_t*) desc;
423
424     desc_t *tgt = (desc_t*) qset_start (arr_desc->value);
425
426     while (NULL != tgt) {
427       fprintf (stream, "\tdesc_%i:arr -> desc_%i:HEAD;\n",
428                desc->id, tgt->id);
429
430       tgt = (desc_t*) qset_next (arr_desc->value);
431     }
432   }
433
434   fprintf (stream, "\n");
435 }
436
437
438 /* ===================================================
439    Exported Implementation:
440    =================================================== */
441 /* Find the given descriptor's entry for the given entity */
442 qset_t *get_entry (desc_t *desc, entity *ent)
443 {
444
445   if (desc->kind == object) {
446     obj_desc_t *obj_desc = (obj_desc_t*) desc;
447     int i;
448     const int n_fields = obj_desc->n_fields;
449
450     for (i = 0; i < n_fields; i ++) {
451       if (ent == obj_desc->fields [i]) {
452         return (obj_desc->values [i]);
453       }
454     }
455
456     assert (0 && "entry not found");
457   } else if (desc->kind == array) {
458     arr_desc_t *arr_desc = (arr_desc_t*) desc;
459
460     return (arr_desc->value);
461   } else {
462     assert (0 && "invalid descriptor");
463     return NULL;
464   }
465 }
466
467
468 /* get a new descriptor for the given type at the given node */
469 desc_t *new_name (type *tp, ir_node *node, int ctx)
470 {
471   desc_t *desc = NULL;
472
473   assert ((is_Class_type (tp) || is_Array_type (tp)) && "unsuitable type");
474
475   DBGPRINT (2, (stdout, "new_name(): new name for type \"%s\"\n",
476                 get_type_name (tp)));
477   fflush (stdout);
478
479   if (is_Class_type (tp)) {
480     obj_desc_t *obj_desc = NALLOC(sizeof(*obj_desc));
481     int i;
482     int n_fields;
483
484     obj_desc->kind = object;
485     obj_desc->fields = collect_fields (tp);
486
487     for (n_fields = 0; (NULL != obj_desc->fields [n_fields]); n_fields ++) {
488       /* nothing, just count ... */
489     }
490
491     obj_desc->n_fields = n_fields;
492     obj_desc->values = (qset_t**) NALLOC (n_fields * sizeof (qset_t));
493
494     for (i = 0; i < n_fields; i ++) {
495       obj_desc->values [i] = qset_new (N_INITIAL_OJBS, qset_obst);
496     }
497
498     desc = (desc_t*) obj_desc;
499   } else if (is_Array_type (tp)) {
500     arr_desc_t *arr_desc = (arr_desc_t*) NALLOC (sizeof (arr_desc_t));
501
502     arr_desc->kind = array;
503     arr_desc->value = qset_new (N_INITIAL_OJBS, qset_obst);
504
505     desc = (desc_t*) arr_desc;
506   }
507
508   desc->id    = name_id ++;
509   desc->col_idx = 0;
510   desc->tp    = tp;
511   desc->visit = FALSE;
512   desc->ctx   = ctx;
513   desc->node  = node;
514
515   desc->prev  = all_descs;
516   all_descs = desc;
517
518   return (desc);
519 }
520
521 # define N_GLOB_INITIAL_FIELDS  20
522 static obj_desc_t *obj_glob = NULL;
523 static int n_glob_fields = N_GLOB_INITIAL_FIELDS;
524
525 /* get a new descriptor for the given (presumably static) entity */
526 desc_t *new_ent_name (entity *ent)
527 {
528   int i;
529   int missing = TRUE;
530   type *tp = get_entity_type (ent);
531
532   assert (is_Pointer_type (tp));
533   tp = get_pointer_points_to_type (tp);
534   assert (is_Class_type (tp));
535
536   DBGPRINT (2, (stdout, "new_ent_name(): new name for entity \"%s\"\n",
537                 get_entity_name (ent)));
538   DBGEXE (2, (fflush (stdout)));
539
540   assert (((allocation_static == get_entity_allocation (ent)) ||
541            (allocation_automatic == get_entity_allocation (ent))) &&
542           "not a static/automatic field");
543
544   if (NULL == obj_glob) {
545     obj_glob = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
546
547     obj_glob->id   = name_id ++;
548     obj_glob->ctx  = -1;
549     obj_glob->col_idx = 0;
550     obj_glob->visit = FALSE;
551     obj_glob->kind = object;
552     obj_glob->tp   = get_glob_type ();
553     obj_glob->node = NULL;
554
555     obj_glob->n_fields = 0;
556     obj_glob->fields = (entity**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (entity*));
557     obj_glob->values = (qset_t**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (qset_t*));
558
559     obj_glob->prev = all_descs;
560     all_descs = (desc_t*) obj_glob;
561   }
562
563   for (i = 0; missing && (i < obj_glob->n_fields); i ++) {
564     if (ent == obj_glob->fields [i]) {
565       missing = FALSE;
566     }
567   }
568
569   if (missing) {
570     if (obj_glob->n_fields == n_glob_fields) {
571       entity **fields = obj_glob->fields;
572       qset_t **values = obj_glob->values;
573
574       n_glob_fields *= 2;
575       obj_glob->fields = (entity**) NALLOC (n_glob_fields * sizeof (entity*));
576       obj_glob->values = (qset_t**) NALLOC (n_glob_fields * sizeof (qset_t*));
577
578       memcpy (obj_glob->fields, fields, obj_glob->n_fields * sizeof (entity*));
579       memcpy (obj_glob->values, values, obj_glob->n_fields * sizeof (qset_t*));
580
581       /* free (fields); */
582       /* free (values); */
583     }
584
585     obj_glob->fields [obj_glob->n_fields   ] = ent;
586     obj_glob->values [obj_glob->n_fields ++] = qset_new (N_INITIAL_OJBS, qset_obst);
587   }
588
589   return ((desc_t*) obj_glob);
590 }
591 # undef N_GLOB_INITIAL_FIELDS
592
593 /* Dump all names to a file of the given name */
594 void pto_dump_names (const char *name)
595 {
596   desc_t *desc = all_descs;
597   FILE *stream = fopen (name, "w");
598
599   errno = 0;
600   if  (NULL == stream) {
601     fprintf (stderr, "pto_dump_names(): unable to open %s (%s)\n",
602              name, strerror (errno));
603     return;
604   }
605
606   pto_name_dump_start (stream);
607
608   while (NULL != desc) {
609     pto_name_dump_desc (desc, stream);
610
611     desc = desc->prev;
612   }
613
614   pto_name_dump_finish (stream);
615   fclose (stream);
616 }
617
618 /* Initialise the name module */
619 void pto_name_init (void)
620 {
621   DBGPRINT (3, (stdout, "(%s:%i) pto_name_init()\n", __FILE__, __LINE__));
622   assert (NULL == name_obst);
623   assert (NULL == qset_obst);
624
625   name_obst = xmalloc (sizeof(*name_obst));
626   qset_obst = xmalloc (sizeof(*qset_obst));
627
628   obstack_init (name_obst);
629   obstack_init (qset_obst);
630 }
631
632 /* Cleanup the name module */
633 void pto_name_cleanup (void)
634 {
635   DBGPRINT (3, (stdout, "(%s:%i) pto_name_cleanup()\n", __FILE__, __LINE__));
636   obstack_free (name_obst, NULL);
637   obstack_free (qset_obst, NULL);
638
639   memset (name_obst, 0x00, sizeof (struct obstack));
640   memset (qset_obst, 0x00, sizeof (struct obstack));
641
642   free (name_obst);
643   free (qset_obst);
644
645   name_obst = NULL;
646   qset_obst = NULL;
647 }
648
649 \f
650 /*
651   $Log$
652   Revision 1.11  2005/01/05 14:25:54  beck
653   renames all is_x*_type() functions to is_X*_type() to prevent name clash with EDG fronten
654
655   Revision 1.10  2004/12/22 14:43:14  beck
656   made allocations C-like
657
658   Revision 1.9  2004/12/21 15:34:09  beck
659   removed C99 constructs
660   make const float
661   add default return
662
663   Revision 1.8  2004/12/15 13:30:30  liekweg
664   use DBGEXE correctly; print yet nicer names
665
666   Revision 1.7  2004/12/15 09:18:18  liekweg
667   pto_name.c
668
669   Revision 1.6  2004/12/06 12:52:09  liekweg
670   colorize name dump
671
672   Revision 1.4  2004/11/30 15:49:27  liekweg
673   include 'dump'
674
675   Revision 1.3  2004/11/30 14:47:54  liekweg
676   fix initialisation; do correct iteration
677
678   Revision 1.2  2004/11/24 14:53:56  liekweg
679   Bugfixes
680
681   Revision 1.1  2004/11/18 16:37:34  liekweg
682   rewritten
683
684
685 */