inter_arity bugfix
[libfirm] / ir / ana2 / pto_util.c
1 /* -*- c -*- */
2
3 /*
4  * Project:     libFIRM
5  * File name:   ir/ana2/pto_util.c
6  * Purpose:     Pto Utilities
7  * Author:      Florian
8  * Modified by:
9  * Created:     Mon 18 Oct 2004
10  * CVS-ID:      $Id$
11  * Copyright:   (c) 1999-2004 Universität Karlsruhe
12  * Licence:     This file is protected by GPL -  GNU GENERAL PUBLIC LICENSE.
13  */
14
15
16 # ifdef HAVE_CONFIG_H
17 #  include <config.h>
18 # endif
19
20 # include "pto_util.h"
21
22 # include <malloc.h>
23 # include <assert.h>
24 # include <string.h>
25 # include <obstack.h>
26
27 # include "irnode.h"
28 # include "irgwalk.h"
29 # include "xmalloc.h"
30 # include "entity.h"
31
32 int get_pto_verbose (void);     /* grrr, can't include pto.h */
33
34 # define DBGPRINT(lvl, msg) if (get_pto_verbose () > lvl) { fprintf msg; }
35
36 static int pto_id = 0;          /* only for pto_t->kind */
37
38 static obj_desc_t *obj_descrs = NULL; /* list of all descrs */
39
40 /*
41   See whether the given entity is a field.
42 */
43 static int is_field (entity *ent)
44 {
45   type *tp = get_entity_type (ent);
46
47   if (is_primitive_type (tp) || is_pointer_type (tp)) {
48     return (TRUE);
49   } else {
50     return (FALSE);
51   }
52 }
53
54 /*
55   Helper to collect_fields(type*): collect all fields of the given
56   clazz and its super classes into the given obstack.
57 */
58 # define obstack_chunk_alloc xmalloc
59 # define obstack_chunk_free free
60
61 static void _collect_fields (type *clazz, struct obstack *obst)
62 {
63   int n_members = get_class_n_members (clazz);
64   int n_supers  = get_class_n_supertypes (clazz);
65   int i;
66
67   for (i = 0; i < n_members; i ++) {
68     entity *ent = get_class_member (clazz, i);
69
70     if (is_field (ent)) {
71       obstack_ptr_grow (obst, ent);
72
73       DBGPRINT (4, (stdout, "%s: add entity \"%s.%s\"\n",
74                     __FUNCTION__,
75                     get_type_name (clazz),
76                     get_entity_name (ent)));
77     }
78   }
79
80   for (i = 0; i < n_supers; i ++) {
81     type *s_clazz = get_class_supertype (clazz, i);
82
83     _collect_fields (s_clazz, obst);
84   }
85 }
86
87 /*
88   Collect the fields of the given class and its super classes into an array.
89   The last entry of the array is written NULL.
90 */
91 static entity **collect_fields (type *clazz)
92 {
93   if (NULL != get_type_link (clazz)) {
94     DBGPRINT (3, (stdout, "%s: reusing field list for \"%s\"\n",
95                   __FUNCTION__, get_type_name (clazz)));
96
97     return ((entity **) get_type_link (clazz));
98   } else {
99     DBGPRINT (2, (stdout, "%s: new field list for \"%s\"\n",
100                   __FUNCTION__, get_type_name (clazz)));
101   }
102
103   struct obstack obst;
104
105   obstack_init (&obst);
106
107   _collect_fields (clazz, &obst);
108
109   /* append terminating NULL */
110   int *the_null = NULL;
111   obstack_ptr_grow (&obst, the_null);
112
113   int n_fields = obstack_object_size (&obst) / sizeof (void*);
114
115   entity ** fields = (entity**) xmalloc (n_fields * sizeof (entity*));
116   void *tmp = obstack_finish (&obst);
117
118   memcpy (fields, tmp, n_fields * sizeof (entity*));
119
120   obstack_free (&obst, NULL);
121
122   set_type_link (clazz, (void*) fields);
123
124   return (fields);
125 }
126 # undef obstack_chunk_alloc
127 # undef obstack_chunk_free
128
129
130 /*
131   Environment for find_irg_args
132 */
133 typedef struct find_irg_args_env {
134   ir_node **args;
135   ir_node *arg;
136 } find_irg_args_env_t;
137
138 /*
139   Helper for find_irg_args
140 */
141 static void find_irg_arg (ir_node *node, void *env)
142 {
143   find_irg_args_env_t *arg_env = (find_irg_args_env_t*) env;
144
145   if (iro_Proj == get_irn_opcode (node)) {
146     if (arg_env->arg == get_Proj_pred (node)) {
147       long n = get_Proj_proj (node);
148
149       assert (! arg_env->args [n]);
150
151       arg_env->args [n] = node;
152     }
153   }
154 }
155
156 /*
157   Print the given obj desc to stdout
158 */
159 static void obj_desc_print (obj_desc_t *obj)
160 {
161   if (obj_kind_obj == obj->kind) {
162     /* object desc */
163     obj_obj_desc_t *obj_obj = (obj_obj_desc_t*) obj;
164     int i;
165
166     fprintf (stdout, "obj desc 0x%08x for type \"%s\"\n",
167              (int) obj, get_type_name (obj->tp));
168
169     for (i = 0; i < obj_obj->n_fields; i ++) {
170       fprintf (stdout, " \"%s\" -> ", get_entity_name (obj_obj->fields [i]));
171       qset_print (obj_obj->vals [i], stdout);
172     }
173
174   } else if (obj_kind_array == obj->kind) {
175     /* array desc */
176     obj_arr_desc_t *obj_arr = (obj_arr_desc_t*) obj;
177
178     fprintf (stdout, "arr desc 0x%08x for type \"%s\"\n",
179              (int) obj, get_type_name (obj->tp));
180
181     fprintf (stdout, " [] -> ");
182     qset_print (obj_arr->val, stdout);
183   } else {
184     fprintf (stderr, "%s:%i: Invalid desc\n", __FILE__, __LINE__);
185   }
186 }
187
188 /*
189   Get the entity of a ptr
190 */
191 entity *get_ptr_ent (ir_node *ptr)
192 {
193   entity *ent = NULL;
194   const opcode ptr_op = get_irn_opcode (ptr);
195   switch (ptr_op) {
196   case (iro_Sel): {
197     ent = get_Sel_entity (ptr);
198   } break;
199
200   case (iro_SymConst): {
201     ent = get_SymConst_entity (ptr);
202   } break;
203
204   default: {
205     fprintf (stderr, "%s: no ent for ptr=%s[%ld]\n",
206              __FUNCTION__,
207              get_op_name (get_irn_op (ptr)),
208              get_irn_node_nr (ptr));
209     assert (0);
210   }
211   }
212
213   return (ent);
214 }
215
216
217 /*
218   Ctors for the pto types
219 */
220
221 /*
222   Create a new Object Description for the given type
223 */
224 obj_desc_t *obj_desc_new (type *tp)
225 {
226   int i;
227   obj_desc_t *res = NULL;
228
229   if (is_array_type (tp)) {
230     obj_arr_desc_t *arr_res = (obj_arr_desc_t*) xmalloc (sizeof (obj_arr_desc_t));
231
232     arr_res->val = qset_new (N_INITIAL_OBJS);
233
234     res = (obj_desc_t*) arr_res;
235     res->kind = obj_kind_array;
236
237     DBGPRINT (0, (stdout, "%s: new ARRAY desc 0x%08x for %s\n",
238              __FUNCTION__, (int) res, get_type_name (tp)));
239   } else if (is_class_type (tp)) {
240     obj_obj_desc_t *obj_res = (obj_obj_desc_t*) xmalloc (sizeof (obj_obj_desc_t));
241     int n_fields = 0;
242     entity **tmp;
243
244     DBGPRINT (0, (stdout, "%s: new CLAZZ desc 0x%08x for %s\n",
245              __FUNCTION__, (int) obj_res, get_type_name (tp)));
246
247     obj_res->fields = collect_fields (tp);
248
249     /* grr, must count */
250     for (tmp = obj_res->fields; NULL != *tmp; tmp ++) {
251       n_fields ++;
252     }
253     obj_res->n_fields = n_fields;
254
255     obj_res->vals = (qset_t **) xmalloc (n_fields * sizeof (qset_t*));
256
257     for (i = 0; i < n_fields; i ++) {
258       obj_res->vals [i] = qset_new (N_INITIAL_OBJS);
259     }
260
261     res = (obj_desc_t*) obj_res;
262     res->kind = obj_kind_obj;
263   } else {
264     assert (0 && "unknown type");
265   }
266
267   res->tp = tp;
268
269   res->next = obj_descrs;
270   obj_descrs = res;
271 # ifdef PTO_DUMMY
272   res->is_dummy = FALSE;
273 # endif /* defined PTO_DUMMY */
274
275   return (res);
276 }
277
278 # ifdef PTO_DUMMY
279 /*
280   Mark an obj desc as a dummy
281 */
282 void obj_desc_set_dummy (obj_desc_t *obj_desc)
283 {
284   obj_desc->is_dummy = TRUE;
285 }
286
287 /*
288   Say whether an obj desc is a dummy
289 */
290 int obj_desc_is_dummy (obj_desc_t *obj_desc)
291 {
292   return (obj_desc->is_dummy);
293 }
294 # endif /* defined PTO_DUMMY */
295
296 /*
297   Deallocate an obj desc
298 */
299 void obj_desc_delete (obj_desc_t *obj_desc)
300 {
301   if (obj_kind_obj == obj_desc->kind) {
302     /* object desc */
303     obj_obj_desc_t *obj_obj = (obj_obj_desc_t*) obj_desc;
304     int i;
305
306     memset (obj_obj->fields, 0x00, obj_obj->n_fields * sizeof (entity*));
307     free (obj_obj->fields);
308
309     for (i = 0; i < obj_obj->n_fields; i ++) {
310       qset_delete (obj_obj->vals [i]);
311     }
312
313     memset (obj_obj->vals, 0x00, obj_obj->n_fields * sizeof (entity*));
314     free (obj_obj->vals);
315
316     memset (obj_obj, 0x00, sizeof (obj_obj_desc_t));
317
318     free (obj_obj);
319   } else {
320     /* array desc */
321     obj_arr_desc_t *obj_arr = (obj_arr_desc_t*) obj_desc;
322
323     qset_delete (obj_arr->val);
324
325     memset (obj_arr, 0x00, sizeof (obj_arr_desc_t));
326
327     free (obj_arr);
328   }
329 }
330
331 /*
332   List all obj descs that have been created.  If tp is given non-NULL,
333   only descs for this type are listed, else all types are listed.
334 */
335 void obj_desc_list_all (type *tp)
336 {
337   obj_desc_t *cur = obj_descrs;
338
339   while (NULL != cur) {
340     if ((NULL == tp) || (tp == cur->tp)) {
341       obj_desc_print (cur);
342     }
343
344     cur = cur->next;
345   }
346 }
347
348 /*
349   Create a new pto value containing no names.
350 */
351 pto_t *pto_new_empty (ir_node *node)
352 {
353   pto_t *pto = (pto_t*) xmalloc (sizeof (pto_t));
354
355   pto->kind = &pto_id;
356   pto->node = node;
357   pto->objs = qset_new (N_INITIAL_OBJS);
358
359   return (pto);
360 }
361
362 /*
363   Create a new pto value containing a name of the given type.
364 */
365 pto_t *pto_new_name (ir_node *node, type *tp)
366 {
367   pto_t *pto = pto_new_empty (node);
368   obj_desc_t *desc = obj_desc_new (tp);
369
370   qset_insert (pto->objs, desc);
371
372   return (pto);
373 }
374
375 /*
376   Deallocate a pto
377 */
378 void pto_delete (pto_t *pto)
379 {
380   qset_delete (pto->objs);
381
382   memset (pto, 0x00, sizeof (pto_t));
383
384   free (pto);
385 }
386
387
388 /*
389   Pto types misc ops
390 */
391 /*
392   Sanity checking on a pto_t
393 */
394 void check_pto (pto_t *pto)
395 {
396   assert (&pto_id == pto->kind);
397 }
398
399 /*
400   Add the given name to the given pto.
401 */
402 void pto_add_name (pto_t *pto, obj_desc_t *obj)
403 {
404   qset_insert (pto->objs, obj);
405 }
406
407 /*
408   Add all the given names to the given pto.
409 */
410 void pto_add_all_names (pto_t *pto, qset_t *objs)
411 {
412   qset_insert_all (pto->objs, objs);
413 }
414
415
416 /*
417   Find the arguments of a graph. For a method that has n args, the
418   result array has 'n+1' entries, the last of which is written NULL.
419 */
420 ir_node **find_irg_args (ir_graph *graph)
421 {
422   type *tp = get_entity_type (get_irg_entity (graph));
423   const int n_args = get_method_n_params (tp);
424   ir_node **args = (ir_node**) xmalloc (sizeof (ir_node*) * (n_args+1));
425   ir_node *arg = get_irg_args (graph);
426   find_irg_args_env_t *arg_env =
427     (find_irg_args_env_t*) xmalloc (sizeof (find_irg_args_env_t));
428
429   arg_env->args = args;
430   arg_env->arg  = arg;
431
432   /* or use get_irg_end ?!? */
433   {
434     ir_graph *save = get_current_ir_graph ();
435     set_current_ir_graph (graph);
436     irg_walk (get_irg_end (graph), find_irg_arg, NULL, arg_env);
437     set_current_ir_graph (save);
438   }
439
440   free (arg_env);
441
442   args [n_args] = NULL;
443
444   return (args);
445 }
446
447 /*
448   Perform a lookup of the contents of the given field in the given pto
449 */
450 qset_t *pto_lookup (obj_desc_t *obj_desc, entity *ent)
451 {
452   qset_t *res = NULL;
453
454   if (obj_kind_obj == obj_desc->kind) {
455     /* obj lookup */
456     obj_obj_desc_t *obj_obj = (obj_obj_desc_t*) obj_desc;
457     int i;
458
459     assert (NULL != ent);
460
461     for (i = 0; NULL != obj_obj->fields [i]; i ++) {
462       if (obj_obj->fields [i] == ent) {
463         break;
464       }
465     }
466
467     assert (obj_obj->fields [i]); /* this *must* find a field */
468
469     res = obj_obj->vals [i];
470   } else {
471     /* array lookup */
472     obj_arr_desc_t *arr_obj = (obj_arr_desc_t*) obj_desc;
473
474     assert (NULL == ent);
475
476     res = arr_obj->val;
477   }
478
479   return (res);
480 }
481
482 /*
483   Enter the given ptr values into the given field of the given pto
484 */
485 void pto_enter (obj_desc_t *obj_desc, entity *ent, pto_t *pto)
486 {
487   if (obj_kind_obj == obj_desc) {
488     /* obj enter */
489     obj_obj_desc_t *obj_obj = (obj_obj_desc_t*) obj_desc;
490     int i;
491
492     for (i = 0; NULL != obj_obj->fields [i]; i ++) {
493       if (obj_obj->fields [i] == ent) {
494         break;
495       }
496     }
497
498     assert (obj_obj->fields [i]); /* this *must* find a field */
499
500     qset_insert_all (obj_obj->vals [i], pto->objs);
501   } else {
502     /* array enter */
503     assert (0 && "array enter not yet implemented");
504   }
505 }
506
507 \f
508 /*
509   $Log$
510   Revision 1.3  2004/11/04 14:58:38  liekweg
511   expanded pto, added initialisation, added debugging printing
512
513   Revision 1.2  2004/10/25 11:59:45  liekweg
514   Copy Only works
515
516   Revision 1.1  2004/10/22 15:10:51  liekweg
517   moved utils to pto_util
518
519
520  */