28d879aa6cab46279dc9fa224fdbd48302b180b1
[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
30 # include "irnode.h"
31 # include "irprog.h"
32 # include "xmalloc.h"
33
34 # include "pto_debug.h"
35
36 /* Local Defines: */
37 # define obstack_chunk_alloc xmalloc
38 # define obstack_chunk_free free
39
40 # define NALLOC(size)   obstack_alloc (name_obst, size)
41
42 /* Local Data Types: */
43
44 /* Local Variables: */
45 struct obstack *qset_obst = NULL;
46 struct obstack *name_obst = NULL;
47
48 /* Local Prototypes: */
49
50 /* ===================================================
51    Local Implementation:
52    =================================================== */
53 /* See whether the given entity is a field. */
54 static int is_field (entity *ent)
55 {
56   type *tp = get_entity_type (ent);
57
58   if (is_primitive_type (tp) || is_pointer_type (tp)) {
59     /* actually, we could get by by restricting ourselves to pointer types */
60     return (TRUE);
61   } else {
62     return (FALSE);
63   }
64 }
65
66 /* Helper to collect_fields(type*): collect all fields of the given
67   clazz and its super classes into the given obstack. */
68 static void _collect_fields (type *clazz, struct obstack *obst)
69 {
70   int n_members = get_class_n_members (clazz);
71   int n_supers  = get_class_n_supertypes (clazz);
72   int i;
73
74   for (i = 0; i < n_members; i ++) {
75     entity *ent = get_class_member (clazz, i);
76
77     if (is_field (ent)) {
78       if (allocation_static != get_entity_allocation (ent)) {
79         obstack_ptr_grow (obst, ent);
80       }
81     }
82   }
83
84   for (i = 0; i < n_supers; i ++) {
85     type *s_clazz = get_class_supertype (clazz, i);
86
87     _collect_fields (s_clazz, obst);
88   }
89 }
90
91 /* Collect the fields of the given class and its super classes into an array.
92   The last entry of the array is written NULL. */
93 static entity **collect_fields (type *clazz)
94 {
95   if (NULL != get_type_link (clazz)) {
96     DBGPRINT (3, (stdout, "%s: reusing field list for \"%s\"\n",
97                   __FUNCTION__, get_type_name (clazz)));
98
99     return ((entity **) get_type_link (clazz));
100   } else {
101     DBGPRINT (2, (stdout, "%s: new field list for \"%s\"\n",
102                   __FUNCTION__, get_type_name (clazz)));
103   }
104
105   struct obstack obst;
106
107   obstack_init (&obst);
108
109   _collect_fields (clazz, &obst);
110
111   /* append terminating NULL */
112   int *the_null = NULL;
113   obstack_ptr_grow (&obst, the_null);
114
115   int n_fields = obstack_object_size (&obst) / sizeof (void*);
116
117   entity ** fields = (entity**) NALLOC (n_fields * sizeof (entity*));
118   void *tmp = obstack_finish (&obst);
119
120   memcpy (fields, tmp, n_fields * sizeof (entity*));
121
122   obstack_free (&obst, NULL);
123
124   set_type_link (clazz, (void*) fields);
125
126   return (fields);
127 }
128
129
130
131 /* ===================================================
132    Exported Implementation:
133    =================================================== */
134 static desc_t *all_descs = NULL;
135
136 /* get a new descriptor for the given type at the given node */
137 desc_t *new_name (type *tp, ir_node *node)
138 {
139   desc_t *desc = NULL;
140
141   assert ((is_class_type (tp) || is_array_type (tp)) && "unsuitable type");
142
143   DBGPRINT (2, (stdout, "%s: new name for type \"%s\"\n", __FUNCTION__,
144                 get_type_name (tp)));
145   fflush (stdout);
146
147   if (is_class_type (tp)) {
148     obj_desc_t *obj_desc = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
149     int i;
150     int n_fields;
151
152     obj_desc->kind = object;
153     obj_desc->fields = collect_fields (tp);
154
155     for (n_fields = 0; (NULL != obj_desc->fields [n_fields]); n_fields ++) {
156       /* nothing, just count ... */
157     }
158
159     obj_desc->n_fields = n_fields;
160     obj_desc->values = (qset_t**) NALLOC (n_fields * sizeof (qset_t));
161
162     for (i = 0; i < n_fields; i ++) {
163       obj_desc->values [i] = qset_new (N_INITIAL_OJBS, qset_obst);
164     }
165
166     desc = (desc_t*) obj_desc;
167   } else if (is_array_type (tp)) {
168     arr_desc_t *arr_desc = (arr_desc_t*) NALLOC (sizeof (arr_desc_t));
169
170     arr_desc->kind = array;
171     arr_desc->value = qset_new (N_INITIAL_OJBS, qset_obst);
172
173     desc = (desc_t*) arr_desc;
174   }
175
176   desc->tp   = tp;
177   desc->node = node;
178
179   desc->prev = all_descs;
180   all_descs = desc;
181
182   return (desc);
183 }
184
185 # define N_GLOB_INITIAL_FIELDS  20
186 static obj_desc_t *obj_glob = NULL;
187 static int n_glob_fields = N_GLOB_INITIAL_FIELDS;
188
189 /* get a new descriptor for the given (presumably static) entity */
190 desc_t *new_ent_name (entity *ent)
191 {
192   int i;
193   int missing = TRUE;
194   type *tp = get_entity_type (ent);
195
196   assert (is_pointer_type (tp));
197   tp = get_pointer_points_to_type (tp);
198   assert (is_class_type (tp));
199
200   assert (((allocation_static == get_entity_allocation (ent)) ||
201            (allocation_automatic == get_entity_allocation (ent))) &&
202           "not a static/automatic field");
203
204   if (NULL == obj_glob) {
205     obj_glob = (obj_desc_t*) NALLOC (sizeof (obj_desc_t));
206
207     obj_glob->kind = object;
208     obj_glob->tp   = get_glob_type ();
209     obj_glob->node = NULL;
210
211     obj_glob->n_fields = 0;
212     obj_glob->fields = (entity**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (entity*));
213     obj_glob->values = (qset_t**) NALLOC (N_GLOB_INITIAL_FIELDS * sizeof (qset_t*));
214
215     obj_glob->prev = all_descs;
216     all_descs = (desc_t*) obj_glob;
217   }
218
219   for (i = 0; missing && (i < obj_glob->n_fields); i ++) {
220     if (ent == obj_glob->fields [i]) {
221       missing = FALSE;
222     }
223   }
224
225   if (missing) {
226     if (obj_glob->n_fields == n_glob_fields) {
227       entity **fields = obj_glob->fields;
228       qset_t **values = obj_glob->values;
229
230       n_glob_fields *= 2;
231       obj_glob->fields = (entity**) NALLOC (n_glob_fields * sizeof (entity*));
232       obj_glob->values = (qset_t**) NALLOC (n_glob_fields * sizeof (qset_t*));
233
234       memcpy (obj_glob->fields, fields, obj_glob->n_fields * sizeof (entity*));
235       memcpy (obj_glob->values, values, obj_glob->n_fields * sizeof (qset_t*));
236
237       /* free (fields); */
238       /* free (values); */
239     }
240
241     obj_glob->fields [obj_glob->n_fields   ] = ent;
242     obj_glob->values [obj_glob->n_fields ++] = qset_new (N_INITIAL_OJBS, qset_obst);
243   }
244
245   return ((desc_t*) obj_glob);
246 }
247 # undef N_GLOB_INITIAL_FIELDS
248
249 /* Initialise the name module */
250 void pto_name_init ()
251 {
252   DBGPRINT (3, (stdout, "(%s:%i) %s\n", __FILE__, __LINE__, __FUNCTION__));
253   assert (NULL == name_obst);
254   assert (NULL == qset_obst);
255
256   name_obst = xmalloc (sizeof (struct obstack));
257   qset_obst = xmalloc (sizeof (struct obstack));
258
259   obstack_init (name_obst);
260   obstack_init (qset_obst);
261 }
262
263 /* Cleanup the name module */
264 void pto_name_cleanup ()
265 {
266   DBGPRINT (3, (stdout, "(%s:%i) %s\n", __FILE__, __LINE__, __FUNCTION__));
267   obstack_free (name_obst, NULL);
268   obstack_free (qset_obst, NULL);
269
270   memset (name_obst, 0x00, sizeof (struct obstack));
271   memset (qset_obst, 0x00, sizeof (struct obstack));
272
273   free (name_obst);
274   free (qset_obst);
275
276   name_obst = NULL;
277   qset_obst = NULL;
278 }
279
280 \f
281 /*
282   $Log$
283   Revision 1.2  2004/11/24 14:53:56  liekweg
284   Bugfixes
285
286   Revision 1.1  2004/11/18 16:37:34  liekweg
287   rewritten
288
289
290 */