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