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