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