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