don't put environments on the stack; handle consts
[libfirm] / ir / ana2 / pto_init.c
1 /* -*- c -*- */
2
3 /*
4    Project:     libFIRM
5    File name:   ir/ana/pto_init.c
6    Purpose:     Initialisation Functions
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_init: Initialisation Functions
21 */
22
23 # include <obstack.h>
24 # include <string.h>
25
26 # include "pto.h"
27 # include "pto_init.h"
28 # include "pto_debug.h"
29 # include "pto_comp.h"
30 # include "pto_name.h"
31 # include "pto_util.h"
32
33 # include "typewalk.h"
34 # include "irgwalk.h"
35 # include "xmalloc.h"
36
37 /* Local Defines: */
38 # define obstack_chunk_alloc xmalloc
39 # define obstack_chunk_free  free
40
41 /* Local Data Types: */
42 typedef struct init_env_str
43 {
44   int n_ctxs;
45 } init_env_t;
46
47 typedef struct reset_env_str
48 {
49   int ctx_idx;
50 } reset_env_t;
51
52 /* Local Variables: */
53 extern struct obstack *qset_obst; /* from pto_name */
54
55 static struct obstack *pto_obst = NULL; /* all pto_t's go onto this one */
56
57 /* Local Prototypes: */
58
59 /* ===================================================
60    Local Implementation:
61    =================================================== */
62 /* Allocate a new pto */
63 static pto_t *new_pto (ir_node *node)
64 {
65   pto_t *pto = obstack_alloc (pto_obst, sizeof (pto_t));
66   pto->values = qset_new (N_INITIAL_OJBS, qset_obst);
67
68   return (pto);
69 }
70
71 /* Allocate a new alloc_pto */
72 static alloc_pto_t *new_alloc_pto (ir_node *alloc, int n_ctxs)
73 {
74   int i;
75   alloc_pto_t *alloc_pto = obstack_alloc (pto_obst, sizeof (alloc_pto_t));
76   type *tp;
77
78   assert (op_Alloc == get_irn_op(alloc));
79
80   tp = get_Alloc_type (alloc);
81
82   alloc_pto->ptos = (pto_t**) obstack_alloc (pto_obst, n_ctxs * sizeof (pto_t*));
83
84   for (i = 0; i < n_ctxs; i ++) {
85     desc_t *desc = new_name (tp, alloc, i);
86     alloc_pto->ptos [i] = new_pto (alloc);
87     qset_insert (alloc_pto->ptos [i]->values, desc);
88   }
89
90   return (alloc_pto);
91 }
92
93 /* Allocate a new pto for a symconst */
94 static pto_t* new_symconst_pto (ir_node *symconst)
95 {
96   pto_t *pto;
97   entity *ent;
98   desc_t *desc = NULL;
99
100   assert (op_SymConst == get_irn_op(symconst));
101
102   pto = new_pto (symconst);
103   ent = get_SymConst_entity (symconst);
104
105   /*
106   const char *ent_name = (char*) get_entity_name (ent);
107   const char *own_name = (char*) get_type_name (get_entity_owner (ent));
108   HERE3 ("start", own_name, ent_name);
109   */
110   /* Ok, so if the symconst has a pointer-to-mumble, it's some address
111      calculation, but if it's the mumble itself, it's just the same,
112      except it's presumably a constant of mumble. In any case, we need to
113      branch on this.  "How's that for object fucking oriented? --jwz" */
114   if (is_Pointer_type (get_entity_type (ent))) {
115     desc = new_ent_name (ent);
116   } else if (is_Class_type (get_entity_type (ent))) {
117     desc = new_name (get_entity_type (ent), symconst, -1);
118   } else {
119     fprintf (stderr, "%s: not handled: %s[%li] (\"%s\")\n",
120              __FUNCTION__,
121              get_op_name (get_irn_op (symconst)),
122              get_irn_node_nr (symconst),
123              get_entity_name (ent));
124     assert (0 && "something not handled");
125   }
126
127   qset_insert (pto->values, desc);
128
129   /* HERE3 ("end", own_name, ent_name); */
130
131   return (pto);
132 }
133
134 /* Helper to pto_init --- clear the link fields of class types */
135 static void clear_type_link (type_or_ent *thing, void *_unused)
136 {
137   if (is_type (thing)) {
138     type *tp = (type*) thing;
139
140     if (is_Class_type (tp)) {
141       DBGPRINT (1, (stdout, "%s (\"%s\")\n",
142                     __FUNCTION__,
143                     get_type_name (tp)));
144
145       set_type_link (tp, NULL);
146     }
147   } else if (is_entity (thing)) {
148     entity *ent = (entity*) thing;
149
150     DBGPRINT (1, (stdout, "%s (\"%s\")\n",
151                   __FUNCTION__,
152                   get_entity_name (ent)));
153
154     set_entity_link (ent, NULL);
155   }
156 }
157
158 /* Helper to pto_init_graph --- clear the links of the given node */
159 static void clear_node_link (ir_node *node, void *_unused)
160 {
161   set_irn_link (node, NULL);
162 }
163
164 /* Helper to pto_init_graph --- clear the links of all nodes */
165 static void clear_graph_links (ir_graph *graph)
166 {
167   irg_walk_graph (graph, clear_node_link, NULL, NULL);
168 }
169
170 /* Reset ALL the pto values for a new pass */
171 static void reset_node_pto (ir_node *node, void *env)
172 {
173   reset_env_t *reset_env = (reset_env_t*) env;
174   int ctx_idx = reset_env->ctx_idx;
175   opcode op = get_irn_opcode (node);
176
177   /* HERE ("start"); */
178
179   switch (op) {
180   case (iro_Load):
181   case (iro_Call):
182   case (iro_Block):             /* END BLOCK only */
183   case (iro_Phi): {
184     /* allocate 'empty' pto values */
185     pto_t *pto = new_pto (node);
186     set_node_pto (node, pto);
187   } break;
188
189   case (iro_Alloc): {
190     /* set alloc to 'right' current pto */
191     alloc_pto_t *alloc_pto = (alloc_pto_t*) get_irn_link (node);
192     alloc_pto->curr_pto = alloc_pto->ptos [ctx_idx];
193
194     DBGPRINT (1, (stdout, "%s: setting pto of \"%s[%li]\" for ctx %i\n",
195                   __FUNCTION__,
196                   OPNAME (node),
197                   OPNUM (node),
198                   ctx_idx));
199
200     assert (alloc_pto->curr_pto);
201   } break;
202   case (iro_Const):
203   case (iro_SymConst): {
204       /* nothing, leave as-is */
205     } break;
206
207   default: {
208     /* basically, nothing */
209     DBGPRINT (2, (stdout, "%s: resetting pto of \"%s[%li]\"\n",
210                   __FUNCTION__,
211                   OPNAME (node),
212                   OPNUM (node)));
213     set_node_pto (node, NULL);
214   } break;
215   }
216
217   /* HERE ("end"); */
218 }
219
220 /* Initialise primary name sources */
221 static void init_pto (ir_node *node, void *env)
222 {
223   init_env_t *init_env = (init_env_t*) env;
224   int n_ctxs = init_env->n_ctxs;
225
226   opcode op = get_irn_opcode (node);
227
228   switch (op) {
229   case (iro_SymConst): {
230     if (mode_is_reference (get_irn_mode (node))) {
231       entity *ent = get_SymConst_entity (node);
232       type   *tp = get_entity_type (ent);
233       if (is_Class_type (tp) || is_Pointer_type (tp)) {
234         pto_t *symconst_pto = new_symconst_pto (node);
235         set_node_pto (node, symconst_pto);
236
237         /* debugging only */
238         DBGPRINT (1, (stdout, "%s: new name \"%s\" for \"%s[%li]\"\n",
239                       __FUNCTION__,
240                       get_entity_name (ent),
241                       OPNAME (node),
242                       OPNUM (node)));
243       }
244     }
245   } break;
246
247   case (iro_Alloc): {
248     alloc_pto_t *alloc_pto = new_alloc_pto (node, n_ctxs);
249     type *tp;
250
251     set_alloc_pto (node, alloc_pto);
252
253     tp = get_Alloc_type (node); /* debugging only */
254     DBGPRINT (1, (stdout, "%s: %i names \"%s\" for \"%s[%li]\"\n",
255                   __FUNCTION__,
256                   n_ctxs,
257                   get_type_name (tp),
258                   OPNAME (node),
259                   OPNUM (node)));
260   } break;
261
262   case (iro_Const): {
263     tarval *tv = get_Const_tarval (node);
264
265     /* only need 'NULL' pointer constants */
266     if (mode_P == get_tarval_mode (tv)) {
267       if (get_tarval_null (mode_P) == tv) {
268         pto_t *pto = new_pto (node);
269         set_node_pto (node, pto);
270       }
271     }
272   } break;
273   case (iro_Load):
274   case (iro_Call):
275   case (iro_Phi):
276     /* nothing --- handled by reset_node_pto on each pass */
277     break;
278   default: {
279     /* nothing */
280   } break;
281   }
282 }
283
284
285 /* Initialise the given graph for a new pass run */
286 static void pto_init_graph_allocs (ir_graph *graph)
287 {
288   graph_info_t *ginfo = ecg_get_info (graph);
289   init_env_t *init_env;
290
291   init_env = xmalloc (sizeof (init_env_t));
292   init_env->n_ctxs = ginfo->n_ctxs;
293
294   /* HERE ("start"); */
295
296   irg_walk_graph (graph, init_pto, NULL, init_env);
297
298   /* HERE ("end"); */
299   memset (init_env, 0x00, sizeof (init_env_t));
300   free (init_env);
301 }
302
303 /* ===================================================
304    Exported Implementation:
305    =================================================== */
306 /* "Fake" the arguments to the main method */
307 void fake_main_args (ir_graph *graph)
308 {
309   /* HERE ("start"); */
310
311   entity *ent = get_irg_entity (graph);
312   type *mtp = get_entity_type (ent);
313   ir_node **args = find_irg_args (graph);
314   type *ctp = get_method_param_type (mtp, 1); /* ctp == char[]*[]* */
315   desc_t *arg_desc;
316   pto_t *arg_pto;
317
318   /* 'main' has signature 'void(int, char[]*[]*)' */
319   assert (NULL == args [2]);
320
321   assert (is_Pointer_type (ctp));
322
323   ctp = get_pointer_points_to_type (ctp); /* ctp == char[]*[] */
324
325   assert (is_Array_type (ctp));
326
327   arg_desc = new_name (ctp, args [1], -1);
328   arg_pto = new_pto (args [1]);
329   /* todo: simulate 'store' to arg1[] ?!? */
330   qset_insert (arg_pto->values, arg_desc);
331
332   set_node_pto (args [1], arg_pto);
333
334   DBGPRINT (1, (stdout, "%s:%i (%s[%li])\n",
335                 __FUNCTION__, __LINE__,
336                 OPNAME (args [1]), OPNUM (args [1])));
337
338 # ifdef TEST_MAIN_TYPE
339   ctp = get_array_element_type (ctp); /* ctp == char[]* */
340
341   assert (is_Pointer_type (ctp));
342
343   ctp = get_pointer_points_to_type (ctp); /* ctp == char[] */
344
345   assert (is_Array_type (ctp));
346
347   ctp = get_array_element_type (ctp); /* ctp == char */
348
349   assert (is_primitive_type (ctp));
350 # endif /* defined  TEST_MAIN_TYPE */
351
352   /* HERE ("end"); */
353 }
354
355 /* Initialise the Init module */
356 void pto_init_init ()
357 {
358   pto_obst = (struct obstack*) xmalloc (sizeof (struct obstack));
359
360   obstack_init (pto_obst);
361 }
362
363 /* Cleanup the Init module */
364 void pto_init_cleanup ()
365 {
366   obstack_free (pto_obst, NULL);
367   memset (pto_obst, 0x00, sizeof (struct obstack));
368   free (pto_obst);
369   pto_obst = NULL;
370 }
371
372
373 /* Initialise the Names of the Types/Entities */
374 void pto_init_type_names ()
375 {
376   /* HERE ("start"); */
377   type_walk (clear_type_link, NULL, NULL);
378   /* HERE ("end"); */
379 }
380
381 /* Initialise the given graph for a new pass run */
382 void pto_init_graph (ir_graph *graph)
383 {
384   ir_node **proj_args;
385   graph_info_t *ginfo = ecg_get_info (graph);
386   const int n_ctxs = ginfo->n_ctxs;
387
388   /* only for debugging stuff: */
389   entity *ent = get_irg_entity (graph);
390   const char *ent_name = (char*) get_entity_name (ent);
391   const char *own_name = (char*) get_type_name (get_entity_owner (ent));
392
393   DBGPRINT (2, (stdout, "%s: init \"%s.%s\" for %i ctxs\n",
394                 __FUNCTION__,
395                 own_name, ent_name, n_ctxs));
396
397   /* HERE ("start"); */
398
399   clear_graph_links     (graph);
400   pto_init_graph_allocs (graph);
401
402   /* HERE ("end"); */
403
404   assert (NULL == get_irg_proj_args (graph));
405   proj_args = find_irg_args (graph);
406   set_irg_proj_args (graph, proj_args);
407   assert (proj_args == get_irg_proj_args (graph));
408 }
409
410 /* Reset the given graph for a new pass run */
411 void pto_reset_graph_pto (ir_graph *graph, int ctx_idx)
412 {
413   reset_env_t *reset_env;
414
415   reset_env = (reset_env_t*) xmalloc (sizeof (reset_env_t));
416   reset_env->ctx_idx = ctx_idx;
417
418   /* HERE ("start"); */
419
420   irg_walk_graph (graph, reset_node_pto, NULL, reset_env);
421
422   /* HERE ("end"); */
423   memset (reset_env, 0x00, sizeof (reset_env_t));
424   free (reset_env);
425 }
426
427 \f
428 /*
429   $Log$
430   Revision 1.16  2005/01/14 13:36:50  liekweg
431   don't put environments on the stack; handle consts
432
433   Revision 1.15  2005/01/10 17:26:34  liekweg
434   fixup printfs, don't put environments on the stack
435
436   Revision 1.14  2005/01/05 14:25:54  beck
437   renames all is_x*_type() functions to is_X*_type() to prevent name clash with EDG fronten
438
439   Revision 1.13  2004/12/21 15:07:55  beck
440   removed C99 contructs
441   removed unnecessary allocation
442   removed use of mode_P, use mode_is_reference() instead
443   removed handling of Const with pointer tarvals, these constructs are removed
444
445   Revision 1.12  2004/12/20 17:41:14  liekweg
446   __unused -> _unused
447
448   Revision 1.11  2004/12/20 17:34:35  liekweg
449   fix recursion handling
450
451   Revision 1.10  2004/12/15 13:31:00  liekweg
452   store ctx idx in names
453
454   Revision 1.9  2004/12/15 09:18:18  liekweg
455   pto_name.c
456
457   Revision 1.8  2004/12/02 16:17:51  beck
458   fixed config.h include
459
460   Revision 1.7  2004/11/30 14:47:54  liekweg
461   fix initialisation; do correct iteration
462
463   Revision 1.6  2004/11/26 16:00:41  liekweg
464   recognize class consts vs. ptr-to-class consts
465
466   Revision 1.5  2004/11/24 14:53:56  liekweg
467   Bugfixes
468
469   Revision 1.4  2004/11/20 21:21:56  liekweg
470   Finalise initialisation
471
472   Revision 1.3  2004/11/18 16:37:07  liekweg
473   rewrite
474
475
476 */