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