fixed some depencies between irdump.c and irdumptxt.c
[libfirm] / ir / ana2 / pto.c
1 /* -*- c -*- */
2
3 /*
4  * Project:     libFIRM
5  * File name:   ir/ana2/pto.c
6  * Purpose:     Pto
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.h"
21 # include "pto_util.h"
22 # include "pto_init.h"
23
24 # include "entity.h"
25
26 # include "irnode.h"
27 # include "irprog.h"
28
29 /* # include "eset.h" */
30 # include "irgraph.h"
31 # include "irgwalk.h"
32 # include "irgmod.h"
33 # include "irvrfy.h"
34 # include "trvrfy.h"
35 # include "xmalloc.h"
36
37 # include "typewalk.h"
38 # include "irmemwalk.h"
39
40 # define DBGPRINT(lvl, msg) if (get_pto_verbose () > lvl) { fprintf msg; }
41 # define DBGEXE(lvl, cmd) if (get_pto_verbose () > lvl) { cmd; }
42
43 /*
44   Local Protos
45 */
46 static void pto_node (ir_node*, void*);
47 static void pto_node_pre  (ir_node*, void*);
48 static void pto_node_post (ir_node*, void*);
49
50 /*
51    Get the pto infos of a node
52 */
53 static pto_t *get_pto (ir_node *node)
54 {
55
56
57   return ((pto_t*) get_irn_link (node));
58 }
59
60 /*
61   Propagate pto values up to the given node, and return the propagated
62   value.  This recursion has to stop at important nodes, such as
63   loads and allocs, where pto is computed differently (albeit this may
64   involve more calls to this function for a different ptr value).
65 */
66 static pto_t *compute_pto (ir_node *node, void *env)
67 {
68   pto_t *node_pto = get_pto (node);
69
70   if ((NULL != node_pto) && (pto_is_dummy (node_pto))) {
71     /* weed out initialisation data as good as possible */
72
73     DBGPRINT (0, (stdout, "%s: dummy pto for (%s[%li])\n",
74                   __FUNCTION__,
75                   get_op_name (get_irn_op (node)),
76                   get_irn_node_nr (node)));
77
78     pto_delete (node_pto);
79     node_pto = NULL;
80   }
81
82   if (NULL == node_pto) {
83     DBGPRINT (1, (stdout, "%s: must compute pto for %s[%li]\n",
84                   __FUNCTION__,
85                   get_op_name (get_irn_op (node)),
86                   get_irn_node_nr (node)));
87
88     pto_node (node, env);
89
90     node_pto = get_pto (node);
91   }
92
93   assert (node_pto);
94
95   return (node_pto);
96 }
97
98 /*
99   Transfer the actual arguments to the given call's formal arguments
100 */
101 static void set_call_args (ir_node *call, ir_graph *graph, void *env)
102 {
103   ir_node **args = find_irg_args (graph);
104   int i;
105
106   const int n_call_args = get_irn_arity (call);
107
108   /* call: M x meth_ptr x Arg x Arg x ... x Arg */
109   /* projT(start): Arg x Arg x ... x Arg */
110   /* projM(start): M */
111
112   for (i = 2; i < n_call_args; i ++) {
113     if (NULL != args [i-2]) {
114       if (mode_P == get_irn_mode (args [i-2])) {
115         pto_t *arg_pto = compute_pto (get_irn_n (call, i), env);
116         /* off-by-two because of ProjT bd */
117         set_pto (args [i-2], arg_pto);
118       } else {
119         /* not a pointer value */
120       }
121     }
122   }
123   free (args);
124 }
125
126 /*
127   Transfer the return value of a call to the callR node
128 */
129 static void get_call_ret (ir_node *call, ir_graph *graph, void *env)
130 {
131   entity *ent = get_irg_ent (graph);
132   type *ent_tp = get_entity_type (ent);
133
134   if (NULL != get_pto (call)) {
135     pto_t *old = get_pto (call);
136
137     if (pto_is_dummy (old)) {
138       DBGPRINT (2, (stdout, "%s: dummy pto (0x%08x) from call[%li]\n",
139                     __FUNCTION__, (int) old, get_irn_node_nr (call)));
140     }
141
142     pto_delete (old);
143   }
144
145   if (0 != get_method_n_ress (ent_tp)) {
146     type *ent_ret_tp = get_method_res_type (ent_tp, 0);
147
148     if (mode_P == get_type_mode (ent_ret_tp)) {
149       pto_t *res_pto = get_pto (get_irg_end_block (graph));
150
151       set_pto (call, res_pto);
152     }
153   }
154 }
155
156
157 /*
158   Take care of a single proj node.  Basically a multiplex/dispatch for the
159   different node types that a proj can have as a predecessor.
160 */
161 static void pto_node_proj (ir_node *proj, void *env)
162 {
163   /*
164     pto for proj({proj(start),load,call,alloc,raise?,...}) node
165   */
166   ir_node *in = get_Proj_pred (proj);
167   const opcode in_op = get_irn_opcode (in);
168   const long proj_proj = get_Proj_proj (proj);
169
170   DBGPRINT (3, (stdout, "%s: --> Proj[%li] (%s)\n",
171                 __FUNCTION__,
172                 get_irn_node_nr (proj),
173                 get_op_name (get_irn_op (in))));
174
175   switch (in_op) {
176   case (iro_Start): {
177     /* nothing (handled by proj(proj)) */
178   } break;
179
180   case (iro_Load): {
181     /* copy from load */
182     if (pn_Load_res == proj_proj) {
183       set_pto (proj, compute_pto (in, env));
184     } else {
185       /* ProjM(load) or ProjX(load) - do nothing */
186     }
187   } break;
188
189   case (iro_Store): {
190     /* ProjM (store) or ProjX (store) - nothing */
191   } break;
192
193   case (iro_Alloc): {
194     /* copy from alloc */
195     if (pn_Alloc_res == proj_proj) {
196       set_pto (proj, compute_pto (in, env));
197     } else {
198       /* ProjM(alloc) or ProjX (alloc) -- nothing */
199     }
200   } break;
201
202   case (iro_Raise): {
203     /* ProjX (raise), ProjM (raise) -- nothing */
204   } break;
205
206   case (iro_Call): {
207     if (pn_Call_M_regular == proj_proj) {
208       /* ProjM(call) -- nothing */
209     } else if (pn_Call_T_result == proj_proj) {
210       /* copy return value of call */
211       pto_t *call_pto = get_pto (in);   /* get result from call */
212       assert (call_pto);
213       set_pto (proj, call_pto);
214     } else if (pn_Call_P_value_res_base == proj_proj) {
215       /* wtf? */
216       assert (0 && "what's with pn_Call_P_value_res_base?");
217     } else {
218       /* ProjX (call) or ProjM_exc (call) -- nothing */
219     }
220
221   } break;
222
223   case (iro_Proj): {
224     const ir_node *in_in = get_Proj_pred (in);
225     const opcode in_in_op = get_irn_opcode (in_in);
226
227     switch (in_in_op) {
228     case (iro_Call): {
229       /* projP (projT (call)) */
230       /* copy from projT to projP */
231       pto_t *in_pto = compute_pto (in, env);
232       set_pto (proj, in_pto);
233     } break;
234     case (iro_Start): {
235       /* proj(proj(start)) - make sure the arguments are initialised */
236       assert (get_pto (proj));
237     } break;
238     default: {
239       DBGPRINT (1, (stdout, "%s:%i: proj(proj(%s)) not handled\n",
240                     __FILE__, __LINE__, get_op_name (get_irn_op (in_in))));
241       assert (0);
242     }
243     }
244   } break;
245
246   case (iro_Cast): {
247     /* make sure the input has been analysed */
248     pto_t *cast_pto = compute_pto (in, env);
249     set_pto (proj, cast_pto);
250
251   } break;
252
253   default: {
254     fprintf (stderr, "%s: opcode %s of Node %ld not handled\n",
255              __FUNCTION__,
256              get_op_name (get_irn_op (in)),
257              get_irn_node_nr (in));
258
259     assert (0 && "something not handled");
260   }
261   }
262
263   DBGPRINT (2, (stdout, "%s: Proj (%s)\n",
264                 __FUNCTION__,
265                 get_op_name (get_irn_op (in))));
266 }
267
268 static void pto_node_obj_load (ir_node *load, ir_node *ptr,
269                                entity *ent, void *env)
270 {
271   /*
272     pto for obj load node
273
274     so far:
275     load.ptr analysed
276     todo:
277     look up
278   */
279   const char *ent_name = (char*) get_entity_name (ent);
280   const char *own_name = (char*) get_type_name (get_entity_owner (ent));
281
282   DBGPRINT (1, (stdout, "%s for (%s[%li])\n",
283                 __FUNCTION__,
284                 get_op_name (get_irn_op (ptr)),
285                 get_irn_node_nr (ptr)));
286
287   if (! is_pointer_type (get_entity_type (ent))) {
288     return;
289   }
290
291   if (NULL != get_pto (load)) {
292     pto_t *old = get_pto (load);
293
294     if (pto_is_dummy (old)) {
295       DBGPRINT (1, (stdout, "%s: dummy pto (0x%08x) from load[%li]\n",
296                     __FUNCTION__, (int) old, get_irn_node_nr (load)));
297     }
298
299     pto_delete (old);
300   }
301
302   DBGPRINT (1, (stdout, "%s: obj load from ent (0x%08x) \"%s.%s\"\n",
303                 __FUNCTION__,
304                 (int) ent,
305                 own_name,
306                 ent_name));
307
308   pto_t *ptr_objs = compute_pto (ptr, env);
309   qset_t *objs = ptr_objs->objs;
310   pto_t *res = pto_new_empty (load);
311   obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
312
313   DBGPRINT (1, (stdout, "%s: ptr_pto = ", __FUNCTION__));
314   DBGEXE (1, qset_print (objs, stdout));
315
316   while (NULL != obj_desc) {
317     qset_t *cnts = pto_lookup (obj_desc, ent);
318
319     DBGPRINT (1, (stdout, "%s: cnts = ", __FUNCTION__));
320     DBGEXE (1, qset_print (cnts, stdout));
321
322     pto_add_all_names (res, cnts);
323
324     obj_desc = (obj_desc_t*) qset_next (objs);
325   }
326
327   set_pto (load, res);
328
329   DBGPRINT (1, (stdout, "%s\n", __FUNCTION__));
330 }
331
332 static void pto_node_arr_load (ir_node *load, ir_node *ptr,
333                                entity *ent, void *env)
334 {
335   /*
336     pto for array load node
337
338     so far:
339     load.ptr analysed or can be computed on-the-fly
340     todo:
341     look up
342   */
343   const char *ent_name = (char*) get_entity_name (ent);
344   const char *own_name = (char*) get_type_name (get_entity_owner (ent));
345
346   /* load from array */
347   DBGPRINT (1, (stdout, "%s for (%s[%li])\n",
348                 __FUNCTION__,
349                 get_op_name (get_irn_op (ptr)),
350                 get_irn_node_nr (ptr)));
351
352   if (! is_pointer_type (get_entity_type (ent))) {
353     return;
354   }
355
356   DBGPRINT (1, (stdout, "%s: array load from ent (0x%08x) \"%s.%s\"\n",
357                 __FUNCTION__,
358                 (int) ent,
359                 own_name,
360                 ent_name));
361
362   pto_t *ptr_objs =  compute_pto (ptr, env);
363   qset_t *objs = ptr_objs->objs;
364   pto_t *res = pto_new_empty (load);
365
366   obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
367
368   while (NULL != obj_desc) {
369     qset_t *cnts = pto_lookup (obj_desc, NULL);
370
371     pto_add_all_names (res, cnts);
372
373     obj_desc = (obj_desc_t*) qset_next (objs);
374   }
375
376   set_pto (load, res);
377 }
378
379 static void pto_node_load (ir_node *load, void *env)
380 {
381   /*
382     pto for load node
383
384     so far:
385     load.ptr analysed or can be computed on-the-fly
386     todo:
387     look up
388   */
389   ir_node *ptr = get_Load_ptr (load);
390   const opcode op = get_irn_opcode (ptr);
391   entity *ent = NULL;
392
393   /* check the funny cases */
394   if (iro_Proj == op) {
395     /* then it's an unused Load(this) (or whatever) and we don't need to look at it */
396     DBGPRINT (1, (stderr, "%s: %s[%li] ignored\n",
397                   __FUNCTION__,
398                   get_op_name (get_irn_op (ptr)),
399                   get_irn_node_nr (ptr)));
400     return;
401   } else if (iro_Cast == op) {
402     /* then it's  (whatever) and we don't know where to look at */
403     DBGPRINT (1, (stderr, "%s: %s[%li] ignored\n",
404                   __FUNCTION__,
405                   get_op_name (get_irn_op (ptr)),
406                   get_irn_node_nr (ptr)));
407     return;
408   }
409
410   ent = get_ptr_ent (ptr);
411
412   assert (ent);
413
414   /* array load or obj load? */
415   if ((iro_Sel == op) && (3 == get_irn_arity (ptr))) {
416     pto_node_arr_load (load, ptr, ent,  env);
417   } else {
418     pto_node_obj_load (load, ptr, ent, env);
419   }
420
421 }
422
423 static void pto_node_obj_store (ir_node *store,
424                                 ir_node *ptr,
425                                 entity *ent,
426                                 ir_node *val,
427                                 void *env)
428 {
429   /*
430     pto for obj store node
431
432     so far: ptr analysed or can be computed on-the-fly
433     todo:
434     update
435   */
436
437
438   const char *ent_name = (char*) get_entity_name (ent);
439   const char *own_name = (char*) get_type_name (get_entity_owner (ent));
440
441   DBGPRINT (1, (stdout, "%s: obj store to ent (0x%08x) \"%s.%s\"\n",
442                 __FUNCTION__,
443                 (int) ent, own_name, ent_name));
444
445   pto_t *ptr_pto = compute_pto (ptr, env);
446   pto_t *val_pto = compute_pto (val, env);
447   qset_t *objs = ptr_pto->objs;
448   qset_t *vals = val_pto->objs;
449
450   obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
451
452   DBGPRINT (1, (stdout, "%s: ptr_pto = ", __FUNCTION__));
453   DBGEXE (1, qset_print (objs, stdout));
454
455   DBGPRINT (1, (stdout, "%s: ptr_val = ", __FUNCTION__));
456   DBGEXE (1, qset_print (vals, stdout));
457
458   while (NULL != obj_desc) {
459     qset_t *cnts = pto_lookup (obj_desc, ent);
460
461     qset_insert_all (cnts, vals);
462
463     DBGPRINT (1, (stdout, "%s: cnts = ", __FUNCTION__));
464     DBGEXE (1, qset_print (cnts, stdout));
465
466     obj_desc = (obj_desc_t*) qset_next (objs);
467   }
468
469   DBGPRINT (1, (stdout, "%s\n", __FUNCTION__));
470 }
471
472 static void pto_node_arr_store (ir_node *store,
473                                 ir_node *ptr,
474                                 entity *ent,
475                                 ir_node *val,
476                                 void *env)
477 {
478   /*
479     pto for array store node
480
481     so far: ptr analysed or can be computed on-the-fly
482     todo:
483     update
484   */
485
486   const char *ent_name = (char*) get_entity_name (ent);
487   const char *own_name = (char*) get_type_name (get_entity_owner (ent));
488
489   DBGPRINT (1, (stdout, "%s: array store to ent (0x%08x) \"%s.%s\"\n",
490                 __FUNCTION__,
491                 (int) ent, own_name, ent_name));
492
493   pto_t *ptr_pto = compute_pto (ptr, env);
494   pto_t *val_pto = compute_pto (val, env);
495   qset_t *objs = ptr_pto->objs;
496   qset_t *vals = val_pto->objs;
497
498   obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
499
500   while (NULL != obj_desc) {
501     qset_t *cnts = pto_lookup (obj_desc, NULL);
502
503     qset_insert_all (cnts, vals);
504
505     obj_desc = (obj_desc_t*) qset_next (objs);
506   }
507 }
508
509 static void pto_node_store (ir_node *store, void *env)
510 {
511   /*
512     pto for store node
513
514     so far: ptr analysed or can be computed on-the-fly
515     todo:
516     update
517   */
518
519   ir_node *ptr = get_Store_ptr (store);
520   ir_node *val = get_Store_value (store);
521   const opcode op = get_irn_opcode (ptr);
522   entity *ent = get_ptr_ent (ptr);
523
524   if (mode_P != get_irn_mode (val)) {
525     return;
526   }
527
528   /* array load or obj load? */
529   if ((iro_Sel == op) && (3 == get_irn_arity (ptr))) {
530     pto_node_arr_store (store, ptr, ent, val, env);
531   } else {
532     pto_node_obj_store (store, ptr, ent, val, env);
533   }
534
535 }
536
537 static void pto_node_alloc (ir_node *alloc, void *env)
538 {
539   /*
540     pto for alloc node
541
542     so far: nothing to do
543     todo:
544     invent new name
545   */
546
547   if (NULL == get_pto (alloc)) {
548     type *tp = get_Alloc_type (alloc);
549
550     pto_t *alloc_pto = pto_new_name (alloc, tp);
551     set_pto (alloc, alloc_pto);
552     DBGPRINT (0, (stdout, "%s (%s[%li]): new pto\n",
553                   __FUNCTION__,
554                   get_op_name (get_irn_op (alloc)),
555                   get_irn_node_nr (alloc)));
556   } else {
557     DBGPRINT (0, (stdout, "%s (%s[%li]): reusing pto\n",
558                   __FUNCTION__,
559                   get_op_name (get_irn_op (alloc)),
560                   get_irn_node_nr (alloc)));
561   }
562
563 }
564
565 static void pto_node_free (ir_node *free, void *env)
566 {
567   /*
568     pto for free node
569
570     so far: ptr analysed or can be computed on-the-fly
571     todo:
572     nothing, actually
573  */
574   /* still, copy somthing */
575   ir_node *ptr = get_Free_ptr (free);
576
577   pto_t *ptr_pto = compute_pto (ptr, env);
578   set_pto (free, ptr_pto);
579 }
580
581 static void pto_node_raise (ir_node *raise, void *env)
582 {
583   /*
584     pto for raise node
585
586     so far: ptr analysed or can be computed on-the-fly
587     todo:
588
589  */
590
591   /* right now, just copy something */
592   ir_node *ptr = get_Raise_exo_ptr (raise);
593
594   pto_t *ptr_pto = compute_pto (ptr, env);
595
596   set_pto (raise, ptr_pto);
597 }
598
599 static void pto_node_sel (ir_node *sel, void *env)
600 {
601   /*
602     pto for sel node
603
604     so far: input selected or can be computed on-the-fly
605     todo:
606     just copy (the selected entity is used in the load/store)
607   */
608
609   ir_node *sel_in = get_Sel_ptr (sel);
610   pto_t *sel_pto = compute_pto (sel_in, env);
611
612   if (NULL == sel_pto) {
613     fprintf (stdout, "%s:%i: sel.in = %s[%li]\n",
614              __FUNCTION__, __LINE__,
615              get_op_name (get_irn_op (sel_in)),
616              get_irn_node_nr (sel_in));
617   }
618   assert (sel_pto);
619
620   set_pto (sel, sel_pto);
621 }
622
623 static void pto_node_call (ir_node *call, void *env)
624 {
625   ir_graph *graph = NULL;
626   ir_node *ptr = get_Call_ptr (call);
627   entity *ent = get_ptr_ent (ptr);
628
629   DBGPRINT (1, (stdout, "%s (%s[%li])\n",
630                 __FUNCTION__,
631                 get_op_name (get_irn_op (call)),
632                 get_irn_node_nr (call)));
633
634
635   const char *ent_name = (char*) get_entity_name (ent);
636   const char *own_name = (char*) get_type_name (get_entity_owner (ent));
637
638   /* Todo:  Iterate over all graphs in 'get_implementing_graphs' */
639   graph = get_entity_irg (ent);
640   if (NULL != graph) {
641     if (! get_irg_is_mem_visited (graph)) {
642       DBGPRINT (1, (stdout, " -> visit  graph (0x%08x) of \"%s.%s\"\n",
643                     (int) graph, own_name, ent_name));
644
645       /* compute call arguments */
646       set_call_args (call, graph, env);
647       /* traverse callEd */
648       irg_walk_mem (graph, pto_node_pre, pto_node_post, NULL);
649       /* maybe get result from called graph */
650       get_call_ret (call, graph, env);
651     }
652   } else {
653     DBGPRINT (0, (stdout, "%s:%i: Warning: no graph for ent \"%s.%s\" in call[%li]\n",
654                   __FILE__, __LINE__, own_name, ent_name, get_irn_node_nr (call)));
655   }
656 }
657
658 static void pto_node_ret (ir_node *ret, void *env)
659 {
660   /*
661     pto for return node
662
663     so far:
664     input should be availlable
665     todo:
666     just copy
667   */
668
669   if ((0 != get_Return_n_ress (ret)) &&
670       (mode_P == get_irn_mode (get_Return_res (ret, 0)))) {
671     ir_node *ret_in = get_Return_res (ret, 0);
672
673     pto_t *ret_pto = compute_pto (ret_in, env);
674
675     DBGPRINT (4, (stdout, "--> Return Node (%ld) (%s)\n",
676                   get_irn_node_nr (ret),
677                   get_op_name (get_irn_op (ret))));
678
679     set_pto (ret, ret_pto);
680   } else {
681     /* nothing to do! */
682   }
683 }
684
685 static void pto_node_phi (ir_node *phi, void *env)
686 {
687   /*
688     pto for phi node
689
690     so far:
691     all ins present or can be computed on-the-fly
692     todo:
693     collect ins
694   */
695
696   int i;
697   int n_ins = get_irn_arity (phi);
698   ir_node *in = NULL;
699
700   if (mode_P != get_irn_mode (phi)) {
701     return;
702   }
703
704   assert (0 && "test phi");
705
706   pto_t *phi_pto = get_pto (phi);
707
708   if (NULL == phi_pto) {
709     phi_pto = pto_new_empty (phi);
710     set_pto (phi, phi_pto);
711   }
712
713   for (i = 0; i < n_ins; i ++) {
714     in = get_irn_n (phi, i);
715
716     pto_t *in_pto = compute_pto (in, env);
717
718     DBGPRINT (0, (stdout, "%s: IN PHI Node (%ld) (%s) (pto = 0x%08x)\n",
719                   __FUNCTION__,
720                   get_irn_node_nr (in),
721                   get_op_name (get_irn_op (in)),
722                   (int) in_pto));
723
724     qset_insert_all (phi_pto->objs, in_pto->objs);
725   }
726 }
727
728 static void pto_node_cnst (ir_node *cnst, void *env)
729 {
730   /*
731     pto for const node
732
733     so far: nothing
734     todo:
735     if this represents something nameable, name it
736   */
737   type *tp = get_Const_type (cnst);
738   pto_t *cnst_pto = pto_new_name (cnst, tp); /* WRONG */
739
740
741   set_pto (cnst, cnst_pto);
742 }
743
744 static void pto_node_sym_cnst (ir_node *sym_cnst, void *env)
745 {
746   /*
747     pto for const node
748
749     so far: nothing
750     todo:
751     if this represents something nameable, name it
752   */
753   entity *ent = get_SymConst_entity (sym_cnst);
754   type *tp = get_entity_type (ent);
755
756   if (is_pointer_type (tp)) {
757     tp = get_pointer_points_to_type (tp);
758     pto_t *sym_cnst_pto = (pto_t*) get_entity_link (ent);
759
760     DBGPRINT (2, (stdout, "%s: SymConst (%ld) (%s)\n",
761                   __FUNCTION__,
762                   get_irn_node_nr (sym_cnst),
763                   get_op_name (get_irn_op (sym_cnst))));
764
765
766     if (NULL == sym_cnst_pto) {
767       sym_cnst_pto = pto_new_name (sym_cnst, tp);
768
769       DBGPRINT (1, (stdout, "%s: SymConst (%ld) (%s): NEW PTO\n",
770                     __FUNCTION__,
771                     get_irn_node_nr (sym_cnst),
772                     get_op_name (get_irn_op (sym_cnst))));
773
774       set_entity_link (ent, sym_cnst_pto);
775     } else {
776       DBGPRINT (1, (stdout, "%s: SymConst (%ld) (%s): reusing pto\n",
777                     __FUNCTION__,
778                     get_irn_node_nr (sym_cnst),
779                     get_op_name (get_irn_op (sym_cnst))));
780     }
781
782     set_pto (sym_cnst, sym_cnst_pto);
783   } else {
784     /* nothing to do */
785   }
786 }
787
788 static void pto_node_end_block (ir_node *end, void *env)
789 {
790   /*
791     pto for const node
792
793     so far: all returns are set or can be computed on-the-fly
794     todo:
795     collect results, set to node.
796   */
797   entity *ent = get_irg_entity (get_irn_irg (end));
798   type *tp = get_entity_type (ent);
799
800   DBGPRINT (2, (stdout, "%s: End Block (%ld) (%s)\n",
801                 __FUNCTION__,
802                 get_irn_node_nr (end),
803                 get_op_name (get_irn_op (end))));
804
805   if (0 != get_method_n_ress (tp)) {
806     tp = get_method_res_type (tp, 0);
807
808     if (mode_P == get_type_mode (tp)) {
809       int i;
810       int n_ins = get_irn_arity (end);
811       pto_t *end_pto = pto_new_empty (end);
812
813       for (i = 0; i < n_ins; i ++) {
814         ir_node *ret = get_irn_n (end, i);
815
816         if (iro_Return == get_irn_opcode (ret)) {
817           pto_t *ret_pto = get_pto (ret);
818           assert (ret_pto);
819
820           pto_add_all_names (end_pto, ret_pto->objs);
821         }
822       }
823
824       set_pto (end, end_pto);
825     }
826   }
827 }
828
829 /*
830   Take care of a single node.  Basically a multiplex/dispatch for the
831   different node types.
832 */
833 static void pto_node (ir_node *node, void *env)
834 {
835   const opcode op = get_irn_opcode (node);
836
837   DBGPRINT (1, (stdout, "%s (%s[%li])\n",
838                 __FUNCTION__,
839                 get_op_name (get_irn_op (node)),
840                 get_irn_node_nr (node)));
841
842   switch (op) {
843   case (iro_Start): {
844     /* pto_node_start (node, env); */
845     /* nothing to do */
846
847   } break;
848   case (iro_Load): {
849     pto_node_load (node, env);
850
851   } break;
852   case (iro_Store): {
853     pto_node_store (node, env);
854
855   } break;
856   case (iro_Alloc): {
857     pto_node_alloc (node, env);
858
859   } break;
860   case (iro_Free): {
861     pto_node_free (node, env);
862
863   } break;
864   case (iro_Raise): {
865     pto_node_raise (node, env);
866
867   } break;
868   case (iro_Sel): {
869     pto_node_sel (node, env);
870
871   } break;
872   case (iro_Call): {
873     /* assert (0 && "calls must be handled in main loop"); */
874     pto_node_call (node, env);
875   } break;
876   case (iro_Return): {
877     if (0 < get_Return_n_ress (node)) {
878       pto_node_ret (node, env);
879     }
880   } break;
881   case (iro_Proj): {
882     pto_node_proj (node, env);
883   } break;
884   case (iro_Phi): {
885     pto_node_phi (node, env);
886   } break;
887   case (iro_Const): {
888     pto_node_cnst (node, env);
889   } break;
890   case (iro_SymConst): {
891     pto_node_sym_cnst (node, env);
892   } break;
893   case (iro_Cast): {
894     pto_t *cast_pto = compute_pto (get_Cast_op (node), env);
895     set_pto (node, cast_pto);
896   } break;
897   case (iro_Block): {
898     /* End Block ONLY */
899     pto_node_end_block (node, env);
900   } break;
901   /* all the uninteresting stuff */
902   case (iro_Div):
903   case (iro_Quot):
904   case (iro_Mod):
905   case (iro_DivMod):
906     set_pto (node, NULL);
907     break;
908   default: {
909     /* stopgap measure */
910     DBGPRINT (0, (stdout, "%s: not handled: node[%li].op = %s\n",
911                   __FUNCTION__,
912                   get_irn_node_nr (node),
913                   get_op_name (get_irn_op (node))));
914     assert (0 && "something not handled");
915   }
916   }
917 }
918 static void pto_node_pre (ir_node *node, void *env)
919 {
920   DBGPRINT (1, (stdout, "%s (%s[%li])\n",
921                 __FUNCTION__,
922                 get_op_name (get_irn_op (node)),
923                 get_irn_node_nr (node)));
924
925   pto_init_node (node);
926 }
927
928 static void pto_node_post (ir_node *node, void *env)
929 {
930   DBGPRINT (1, (stdout, "%s (%s[%li])\n",
931                 __FUNCTION__,
932                 get_op_name (get_irn_op (node)),
933                 get_irn_node_nr (node)));
934
935   pto_node (node, env);
936 }
937
938 static int pto_verbose = 0;
939
940 /*
941   Helper to pto_init --- clear the link fields of class types
942 */
943 static void clear_type_link (type_or_ent *thing, void *__unused)
944 {
945   if (is_type (thing)) {
946     type *tp = (type*) thing;
947
948     if (is_class_type (tp)) {
949       DBGPRINT (1, (stdout, "%s (\"%s\")\n",
950                     __FUNCTION__, get_type_name (tp)));
951
952       set_type_link (tp, NULL);
953     }
954   } else if (is_entity (thing)) {
955     entity *ent = (entity*) thing;
956
957     DBGPRINT (1, (stdout, "%s (\"%s\")\n",
958                   __FUNCTION__, get_entity_name (ent)));
959
960     set_entity_link (ent, NULL);
961   }
962 }
963
964 /*
965   Helper to pto_cleanup --- deallocate the field closure lists and clear the link fields of class types
966 */
967 static void free_field_list (type_or_ent *thing, void *__unused)
968 {
969   if (is_type) {
970     type *tp = (type*) thing;
971
972     if (is_class_type (tp)) {
973       if (NULL != get_type_link (tp)) {
974         entity **fields = (entity**) get_type_link (tp);
975
976         free (fields);
977       }
978
979       set_type_link (tp, NULL);
980     }
981   }
982 }
983
984
985 void set_pto (ir_node *node, pto_t *pto)
986 {
987   check_pto (pto);
988
989   set_irn_link (node, (void*) pto);
990 }
991
992 int get_pto_verbose ()
993 {
994   return (pto_verbose);
995 }
996
997 void set_pto_verbose (int verbose)
998 {
999   pto_verbose = verbose;
1000 }
1001
1002 /*
1003   Initialise Pto
1004 */
1005 void pto_init ()
1006 {
1007   type_walk (clear_type_link, NULL, NULL);
1008 }
1009
1010
1011 /*
1012   Run Pto
1013 */
1014 void pto_run (int do_verbose)
1015 {
1016   /* int i; */
1017   set_pto_verbose (do_verbose);
1018   set_pto_verbose (2);
1019
1020   DBGPRINT (0, (stdout, "START PTO\n"));
1021
1022   ir_graph *graph = get_irp_main_irg ();
1023
1024   DBGPRINT (0, (stdout, "START GRAPH (0x%08x) of \"%s.%s\"\n",
1025                 (int) graph,
1026                 get_type_name (get_entity_owner (get_irg_entity (graph))),
1027                 get_entity_name (get_irg_entity (graph))));
1028
1029   /* Set args for main graph */
1030   {
1031     type *meth_tp = get_entity_type (get_irg_entity (graph));
1032     type *param_tp = get_method_param_type (meth_tp, 1);
1033     param_tp = get_pointer_points_to_type (param_tp);
1034
1035     const long n_args =         /* wtf? */
1036       get_method_n_params (meth_tp);
1037     ir_node **args = find_irg_args (graph);
1038     pto_t *main_pto = pto_new_name (args [1], param_tp);
1039     int i;
1040
1041     for (i = 0; i < n_args; i ++) {
1042       DBGPRINT (2, (stdout, "arg [%i] = %s[%ld]\n",
1043                     i,
1044                     args [i] ? get_op_name (get_irn_op (args [i])) : "none",
1045                     args [i] ? get_irn_node_nr (args [i]) : -1));
1046     }
1047     set_pto (args [1], main_pto);
1048
1049     free (args);
1050   }
1051
1052   irg_walk_mem (graph, pto_node_pre, pto_node_post, NULL);
1053
1054   DBGPRINT (0, (stdout, "END   GRAPH (0x%08x)\n", (int) graph));
1055   DBGPRINT (0, (stdout, "END   PTO\n"));
1056
1057   obj_desc_list_all (NULL);
1058 }
1059
1060 /*
1061   Clean Up
1062 */
1063 void pto_cleanup ()
1064 {
1065   type_walk (free_field_list, NULL, NULL);
1066 }
1067
1068
1069 \f
1070 /*
1071  * $Log$
1072  * Revision 1.6  2004/11/09 16:47:09  liekweg
1073  * fix SymConst handling
1074  *
1075  * Revision 1.5  2004/11/08 12:33:06  liekweg
1076  * initialisation; sanitize print levels, misc fixes
1077  *
1078  * Revision 1.4  2004/11/04 14:58:38  liekweg
1079  * expanded pto, added initialisation, added debugging printing
1080  *
1081  * Revision 1.3  2004/10/25 11:59:45  liekweg
1082  * Copy Only works
1083  *
1084  * Revision 1.2  2004/10/21 11:09:37  liekweg
1085  * Moved memwalk stuf into irmemwalk
1086  * Moved lset stuff into lset
1087  * Moved typalise stuff into typalise
1088  *
1089  * Revision 1.1  2004/10/20 14:59:42  liekweg
1090  * Added ana2, added ecg and pto
1091  *
1092  */