67b209b7b3c9e5effcec2564f9c3a3eb90202438
[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 /* Local Prototypes: */
54
55 /* ===================================================
56    Local Implementation:
57    =================================================== */
58 /* See whether the given entity is a field. */
59 static int is_field (entity *ent)
60 {
61   type *tp = get_entity_type (ent);
62
63   if (is_primitive_type (tp) || is_pointer_type (tp)) {
64     /* actually, we could get by by restricting ourselves to pointer types */
65     return (TRUE);
66   } else {
67     return (FALSE);
68   }
69 }
70
71 /* Helper to collect_fields(type*): collect all fields of the given
72   clazz and its super classes into the given obstack. */
73 static void _collect_fields (type *clazz, struct obstack *obst)
74 {
75   int n_members = get_class_n_members (clazz);
76   int n_supers  = get_class_n_supertypes (clazz);
77   int i;
78
79   for (i = 0; i < n_members; i ++) {
80     entity *ent = get_class_member (clazz, i);
81
82     if (is_field (ent)) {
83       if (allocation_static != get_entity_allocation (ent)) {
84         obstack_ptr_grow (obst, ent);
85       }
86     }
87   }
88
89   for (i = 0; i < n_supers; i ++) {
90     type *s_clazz = get_class_supertype (clazz, i);
91
92     _collect_fields (s_clazz, obst);
93   }
94 }
95
96 /* Collect the fields of the given class and its super classes into an array.
97   The last entry of the array is written NULL. */
98 static entity **collect_fields (type *clazz)
99 {
100   if (NULL != get_type_link (clazz)) {
101     DBGPRINT (3, (stdout, "%s: reusing field list for \"%s\"\n",
102                   __FUNCTION__, get_type_name (clazz)));
103
104     return ((entity **) get_type_link (clazz));
105   } else {
106     DBGPRINT (2, (stdout, "%s: new field list for \"%s\"\n",
107                   __FUNCTION__, get_type_name (clazz)));
108   }
109
110   struct obstack obst;
111
112   obstack_init (&obst);
113
114   _collect_fields (clazz, &obst);
115
116   /* append terminating NULL */
117   int *the_null = NULL;
118   obstack_ptr_grow (&obst, the_null);
119
120   int n_fields = obstack_object_size (&obst) / sizeof (void*);
121
122   entity ** fields = (entity**) NALLOC (n_fields * sizeof (entity*));
123   void *tmp = obstack_finish (&obst);
124
125   memcpy (fields, tmp, n_fields * sizeof (entity*));
126
127   obstack_free (&obst, NULL);
128
129   set_type_link (clazz, (void*) fields);
130
131   return (fields);
132 }
133
134 /* Write the intro text for a name dump into the given stream */
135 static void pto_name_dump_start (FILE *stream)
136 {
137   fprintf (stream, "digraph \"Names\" {\n");
138   fprintf (stream, "\tgraph [rankdir=\"LR\", ordering=\"out\"];\n");
139   fprintf (stream, "\tnode [shape=\"record\", style=\"filled\"];\n");
140   fprintf (stream, "\tedge [color=\"black\"];\n");
141   fprintf (stream, "\n");
142 }
143
144 /* Write the extro text for a name dump into the given stream */
145 static void pto_name_dump_finish (FILE *stream)
146 {
147   fprintf (stream, "}\n");
148 }
149
150 /* Write a node for the given descriptor into the given stream */
151 static void pto_name_dump_desc (desc_t *desc, FILE *stream)
152 {
153   type *tp = desc->tp;
154   const char *tp_name = get_type_name (tp);
155
156   fprintf (stream, "\t/* %s \"%s\" */\n",
157            object == desc->kind ? "Object" : "Array",
158            tp_name);
159
160   fprintf (stream, "\tdesc_%i [label=\"<HEAD>type=\\\"%s\\\"",
161            desc->id,
162            tp_name);
163
164   ir_node *nd = desc->node;
165
166   if (NULL != nd) {
167     fprintf (stream, "|<NODE>node=%s\\[%li\\]",
168              get_op_name (get_irn_op (nd)),
169              get_irn_node_nr (nd));
170   }
171
172   if (desc->kind == object) {
173     obj_desc_t *obj_desc = (obj_desc_t*) desc;
174
175     int i;
176     for (i = 0; i < obj_desc->n_fields; i ++) {
177       const char *ent_name = get_entity_name (obj_desc->fields [i]);
178
179       fprintf (stream, "|<%i>%s", i, ent_name);
180     }
181   } else if (array == desc->kind) {
182     arr_desc_t *arr_desc = (arr_desc_t*) desc;
183
184     fprintf (stream, "|<arr>[]");
185   } else {
186     assert (0 && "invalid descriptor");
187   }
188
189   fprintf (stream, "\"];\n");
190   fprintf (stream, "\n");
191
192   /* now the edges */
193   if (desc->kind == object) {
194     obj_desc_t *obj_desc = (obj_desc_t*) desc;
195
196     int i;
197     for (i = 0; i < obj_desc->n_fields; i ++) {
198       desc_t *tgt = (desc_t*) qset_start (obj_desc->values [i]);
199
200       while (NULL != tgt) {
201         fprintf (stream, "\tdesc_%i:%i -> desc_%i:HEAD;\n",
202                  desc->id, i, tgt->id);
203
204         tgt = (desc_t*) qset_next (obj_desc->values [i]);
205       }
206     }
207   } else if (array == desc->kind) {
208     arr_desc_t *arr_desc = (arr_desc_t*) desc;
209
210     desc_t *tgt = (desc_t*) qset_start (arr_desc->value);
211
212     while (NULL != tgt) {
213       fprintf (stream, "\tdesc_%i:arr -> desc_%i:HEAD;\n",
214                desc->id, tgt->id);
215
216       tgt = (desc_t*) qset_next (arr_desc->value);
217     }
218   }
219
220   fprintf (stream, "\n");
221 }
222
223
224 /* ===================================================
225    Exported Implementation:
226    =================================================== */
227 /* Find the given descriptor's entry for the given entity */
228 qset_t *get_entry (desc_t *desc, entity *ent)
229 {
230
231   if (desc->kind == object) {
232     obj_desc_t *obj_desc = (obj_desc_t*) desc;
233     int i;
234     const int n_fields = obj_desc->n_fields;
235
236     for (i = 0; i < n_fields; i ++) {
237       if (ent == obj_desc->fields [i]) {
238         return (obj_desc->values [i]);
239       }
240     }
241
242     assert (0 && "entry not found");
243   } else if (desc->kind = array) {
244     arr_desc_t *arr_desc = (arr_desc_t*) desc;
245
246     return (arr_desc->value);
247   } else {
248     assert (0 && "invalid descriptor");
249   }
250 }
251
252
253 /* get a new descriptor for the given type at the given node */
254 desc_t *new_name (type *tp, ir_node *node)
255 {
256   desc_t *desc = NULL;
257
258   assert ((is_class_type (tp) || is_array_type (tp)) && "unsuitable type");
259
260   DBGPRINT (2, (stdout, "%s: new name for type \"%s\"\n", __FUNCTION__,
261                 get_type_name (tp)));
262   fflush (stdout);
263
264   if (is_class_type (tp)) {
265     obj_desc_t *obj_desc = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
266     int i;
267     int n_fields;
268
269     obj_desc->kind = object;
270     obj_desc->fields = collect_fields (tp);
271
272     for (n_fields = 0; (NULL != obj_desc->fields [n_fields]); n_fields ++) {
273       /* nothing, just count ... */
274     }
275
276     obj_desc->n_fields = n_fields;
277     obj_desc->values = (qset_t**) NALLOC (n_fields * sizeof (qset_t));
278
279     for (i = 0; i < n_fields; i ++) {
280       obj_desc->values [i] = qset_new (N_INITIAL_OJBS, qset_obst);
281     }
282
283     desc = (desc_t*) obj_desc;
284   } else if (is_array_type (tp)) {
285     arr_desc_t *arr_desc = (arr_desc_t*) NALLOC (sizeof (arr_desc_t));
286
287     arr_desc->kind = array;
288     arr_desc->value = qset_new (N_INITIAL_OJBS, qset_obst);
289
290     desc = (desc_t*) arr_desc;
291   }
292
293   desc->id   = name_id ++;
294   desc->tp   = tp;
295   desc->node = node;
296
297   desc->prev = all_descs;
298   all_descs = desc;
299
300   return (desc);
301 }
302
303 # define N_GLOB_INITIAL_FIELDS  20
304 static obj_desc_t *obj_glob = NULL;
305 static int n_glob_fields = N_GLOB_INITIAL_FIELDS;
306
307 /* get a new descriptor for the given (presumably static) entity */
308 desc_t *new_ent_name (entity *ent)
309 {
310   int i;
311   int missing = TRUE;
312   type *tp = get_entity_type (ent);
313
314   assert (is_pointer_type (tp));
315   tp = get_pointer_points_to_type (tp);
316   assert (is_class_type (tp));
317
318   assert (((allocation_static == get_entity_allocation (ent)) ||
319            (allocation_automatic == get_entity_allocation (ent))) &&
320           "not a static/automatic field");
321
322   if (NULL == obj_glob) {
323     obj_glob = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
324
325     obj_glob->id   = name_id ++;
326     obj_glob->kind = object;
327     obj_glob->tp   = get_glob_type ();
328     obj_glob->node = NULL;
329
330     obj_glob->n_fields = 0;
331     obj_glob->fields = (entity**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (entity*));
332     obj_glob->values = (qset_t**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (qset_t*));
333
334     obj_glob->prev = all_descs;
335     all_descs = (desc_t*) obj_glob;
336   }
337
338   for (i = 0; missing && (i < obj_glob->n_fields); i ++) {
339     if (ent == obj_glob->fields [i]) {
340       missing = FALSE;
341     }
342   }
343
344   if (missing) {
345     if (obj_glob->n_fields == n_glob_fields) {
346       entity **fields = obj_glob->fields;
347       qset_t **values = obj_glob->values;
348
349       n_glob_fields *= 2;
350       obj_glob->fields = (entity**) NALLOC (n_glob_fields * sizeof (entity*));
351       obj_glob->values = (qset_t**) NALLOC (n_glob_fields * sizeof (qset_t*));
352
353       memcpy (obj_glob->fields, fields, obj_glob->n_fields * sizeof (entity*));
354       memcpy (obj_glob->values, values, obj_glob->n_fields * sizeof (qset_t*));
355
356       /* free (fields); */
357       /* free (values); */
358     }
359
360     obj_glob->fields [obj_glob->n_fields   ] = ent;
361     obj_glob->values [obj_glob->n_fields ++] = qset_new (N_INITIAL_OJBS, qset_obst);
362   }
363
364   return ((desc_t*) obj_glob);
365 }
366 # undef N_GLOB_INITIAL_FIELDS
367
368 /* Dump all names to a file of the given name */
369 void pto_dump (const char *name)
370 {
371   desc_t *desc = all_descs;
372   FILE *stream = fopen (name, "w");
373
374   errno = 0;
375   if  (NULL == stream) {
376     fprintf (stderr, "%s: unable to open %s (%s)\n",
377              __FUNCTION__, name, strerror (errno));
378     return;
379   }
380
381   pto_name_dump_start (stream);
382
383   while (NULL != desc) {
384     pto_name_dump_desc (desc, stream);
385
386     desc = desc->prev;
387   }
388
389   pto_name_dump_finish (stream);
390   fclose (stream);
391 }
392
393 /* Initialise the name module */
394 void pto_name_init ()
395 {
396   DBGPRINT (3, (stdout, "(%s:%i) %s\n", __FILE__, __LINE__, __FUNCTION__));
397   assert (NULL == name_obst);
398   assert (NULL == qset_obst);
399
400   name_obst = xmalloc (sizeof (struct obstack));
401   qset_obst = xmalloc (sizeof (struct obstack));
402
403   obstack_init (name_obst);
404   obstack_init (qset_obst);
405 }
406
407 /* Cleanup the name module */
408 void pto_name_cleanup ()
409 {
410   DBGPRINT (3, (stdout, "(%s:%i) %s\n", __FILE__, __LINE__, __FUNCTION__));
411   obstack_free (name_obst, NULL);
412   obstack_free (qset_obst, NULL);
413
414   memset (name_obst, 0x00, sizeof (struct obstack));
415   memset (qset_obst, 0x00, sizeof (struct obstack));
416
417   free (name_obst);
418   free (qset_obst);
419
420   name_obst = NULL;
421   qset_obst = NULL;
422 }
423
424 \f
425 /*
426   $Log$
427   Revision 1.3  2004/11/30 14:47:54  liekweg
428   fix initialisation; do correct iteration
429
430   Revision 1.2  2004/11/24 14:53:56  liekweg
431   Bugfixes
432
433   Revision 1.1  2004/11/18 16:37:34  liekweg
434   rewritten
435
436
437 */