fixed end block handling
[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
23 # include "entity.h"
24
25 # include "irnode_t.h"
26 # include "irprog_t.h"
27
28 /* # include "eset.h" */
29 # include "irgraph.h"
30 # include "irgwalk.h"
31 # include "irgmod.h"
32 # include "irvrfy.h"
33 # include "trvrfy.h"
34 # include "xmalloc.h"
35
36 # include "irmemwalk.h"
37
38 # ifndef TRUE
39 #  define TRUE 1
40 #  define FALSE 0
41 # endif /* not defined TRUE */
42
43 typedef struct pto_str
44 {
45   int *dummy;
46 } pto_t;
47
48 /*
49   Local Protos
50 */
51 static void pto_node (ir_node*, void*);
52
53 /*
54    Le Flag
55 */
56 static int verbose = TRUE;
57
58 /*
59 Create a new pto value
60 */
61 static pto_t *new_pto (void)
62 {
63   pto_t *pto = (pto_t*) xmalloc (sizeof (pto_t));
64
65   return (pto);
66 }
67
68
69 /*
70    Get the pto infos of a node
71 */
72 static pto_t *get_pto (ir_node *node)
73 {
74   return ((pto_t*) node->link);
75 }
76
77 static pto_t *compute_pto (ir_node *node, void *env)
78 {
79   pto_t *node_pto = get_pto (node);
80
81   if (NULL == node_pto) {
82     pto_node (node, env);
83
84     node_pto = get_pto (node);
85   }
86
87   assert (node_pto);
88
89   return (node_pto);
90 }
91
92 static void set_pto (ir_node *node, pto_t *ptrs)
93 {
94   node->link = (void*) ptrs;
95 }
96
97 /*
98   Take care of a single proj node.  Basically a multiplex/dispatch for the
99   different node types that a proj can have as a predecessor.
100 */
101 static void pto_node_proj (ir_node *proj, void *env)
102 {
103   /*
104     pto for proj({proj(start),load,call,alloc,raise?,...}) node
105
106     so far:
107     whatever it is we have in front of us, it's analyzed.
108     todo:
109     we just pick up the pointer.
110   */
111   ir_node *in = get_Proj_pred (proj);
112   const opcode in_op = get_irn_opcode (in);
113   const long proj_proj = get_Proj_proj (proj);
114
115   fprintf (stdout, "%s: --> Proj[%li] (%s)\n",
116            __FUNCTION__,
117            get_irn_node_nr (proj),
118            get_op_name (get_irn_op (in)));
119
120   switch (in_op) {
121   case (iro_Start): {
122     /* nothing (handled by proj(proj)) */
123   } break;
124
125   case (iro_Load): {
126     /* copy from load */
127     if (pn_Load_res == proj_proj) {
128       set_pto (proj, compute_pto (in, env));
129     } else {
130       /* ProjM(load) or ProjX(load) - do nothing */
131     }
132   } break;
133
134   case (iro_Store): {
135     /* ProjM (store) or ProjX (store) - nothing */
136   } break;
137
138   case (iro_Alloc): {
139     /* copy from alloc */
140     if (pn_Alloc_res == proj_proj) {
141       set_pto (proj, compute_pto (in, env));
142     } else {
143       /* ProjM(alloc) or ProjX (alloc) -- nothing */
144     }
145   } break;
146
147   case (iro_Raise): {
148     /* ProjX (raise), ProjM (raise) -- nothing */
149   } break;
150
151   case (iro_Call): {
152     if (pn_Call_M_regular == proj_proj) {
153       /* ProjM(call) -- nothing */
154     } else if (pn_Call_T_result == proj_proj) {
155     /* copy return value of call */
156       set_pto (proj, compute_pto (in, env));
157     } else if (pn_Call_P_value_res_base == proj_proj) {
158       /* wtf? */
159       assert (0 && "what's with pn_Call_P_value_res_base?");
160     } else {
161       /* ProjX (call) or ProjM_exc (call) -- nothing */
162     }
163
164   } break;
165
166   case (iro_Proj): {
167     const ir_node *in_in = get_Proj_pred (in);
168     const opcode in_in_op = get_irn_opcode (in_in);
169
170     assert (iro_Start == in_in_op && "proj (proj (X)) but not X != Start");
171     /* proj(proj(start)) - make sure the arguments are initialised */
172     fprintf (stdout, "pto (proj(%li)) = 0x%08x\n",
173              get_irn_node_nr (proj),
174              (int) get_pto (proj));
175     set_pto (proj, NULL);
176   } break;
177
178   case (iro_Cast): {
179     /* make sure the input has been analysed */
180     pto_t *cast_pto = compute_pto (in, env);
181     set_pto (proj, cast_pto);
182
183   } break;
184
185   default: {
186     fprintf (stderr, "Opcode %s of Node %ld not handled\n",
187              get_op_name (get_irn_op (in)),
188              get_irn_node_nr (in));
189
190     assert (0 && "something not handled");
191   }
192   }
193
194   if (verbose) {
195     fprintf (stdout, "---> Proj (%s)\n", get_op_name (get_irn_op (in)));
196   }
197
198 }
199
200 static void pto_node_load (ir_node *load, void *env)
201 {
202   /*
203     pto for load node
204
205     so far:
206     load.ptr analysed
207     todo:
208     look up
209   */
210
211   /* right now, just copy something */
212   ir_node *ptr = get_Load_ptr (load);
213   const opcode op = get_irn_opcode (ptr);
214   entity *ent = NULL;
215
216   if (iro_Sel == op) {
217     ent = get_Sel_entity (ptr);
218   } else if (iro_SymConst == op) {
219     ent = get_SymConst_entity (ptr);
220   } else if (iro_Proj == op) {
221     /* then it's an unused Load(this) (or whatever) and we don't need to look at it */
222     ent = NULL;
223   } else if (iro_Cast == op) {
224     /* then it's  whatever and we don't know where to look at */
225     ent = NULL;
226   } else {
227     fprintf (stdout, "%s: %s[%li] not handled\n",
228              __FUNCTION__,
229              get_op_name (get_irn_op (ptr)),
230              get_irn_node_nr (ptr));
231     assert (0 && "told ya");
232   }
233
234   if (NULL != ent) {
235     pto_t *ptr_pto = compute_pto (ptr, env);
236
237
238     /* todo: use 'ent' to look up */
239     set_pto (load, ptr_pto);      /* for now */
240   }
241 }
242
243 static void pto_node_store (ir_node *store, void *env)
244 {
245   /*
246     pto for store node
247
248     so far:
249     ptr analysed
250     todo:
251     update
252   */
253
254   /* right now, just copy something */
255   ir_node *ptr = get_Store_ptr (store);
256   const opcode op = get_irn_opcode (ptr);
257   entity *ent = NULL;
258
259   if (iro_Sel == op) {
260     ent = get_Sel_entity (ptr);
261   } else if (iro_SymConst == op) {
262     ent = get_SymConst_entity (ptr);
263   } else {
264     fprintf (stdout, "%s: opcode %s not handled\n",
265              __FUNCTION__, get_op_name (get_irn_op (ptr)));
266     assert (0 && "told ya");
267   }
268
269   pto_t *ptr_pto = compute_pto (ptr, env);
270   /* todo: use 'ent' to look up */
271   fprintf (stdout, "%s: pto (store[%li]) = 0x%08d\n",
272            __FUNCTION__, get_irn_node_nr (ptr), (int) ptr_pto);
273 }
274
275 static void pto_node_alloc (ir_node *alloc, void *env)
276 {
277   /*
278     pto for alloc node
279
280     so far:
281     nothing
282     todo:
283     invent new name
284  */
285
286   pto_t *alloc_pto = (pto_t*) xmalloc (sizeof (pto_t));
287
288   set_pto (alloc, alloc_pto);
289 }
290
291 static void pto_node_free (ir_node *free, void *env)
292 {
293   /*
294     pto for free node
295
296     so far:
297     ptr analysed
298     todo:
299     nothing, actually
300  */
301   /* still, copy somthing */
302   ir_node *ptr = get_Free_ptr (free);
303
304   pto_t *ptr_pto = compute_pto (ptr, env);
305   set_pto (free, ptr_pto);
306 }
307
308 static void pto_node_raise (ir_node *raise, void *env)
309 {
310   /*
311     pto for raise node
312
313     so far:
314     ptr analysed
315     todo:
316
317  */
318
319   /* right now, just copy something */
320   ir_node *ptr = get_Raise_exo_ptr (raise);
321
322   pto_t *ptr_pto = compute_pto (ptr, env);
323
324   set_pto (raise, ptr_pto);
325 }
326
327 static void pto_node_sel (ir_node *sel, void *env)
328 {
329   /*
330     pto for sel node
331
332     so far:
333     input selected
334     todo:
335     just copy
336   */
337
338   ir_node *sel_in = get_Sel_ptr (sel);
339   pto_t *sel_pto = compute_pto (sel_in, env);
340
341   if (NULL == sel_pto) {
342     fprintf (stdout, "%s:%i: sel.in = %s[%li]\n",
343              __FUNCTION__, __LINE__,
344              get_op_name (get_irn_op (sel_in)),
345              get_irn_node_nr (sel_in));
346   }
347   assert (sel_pto);
348
349   set_pto (sel, sel_pto);
350 }
351
352 # ifdef UNSINN
353 static void pto_node_call (ir_node *call, void *env)
354 {
355   int i;
356   int n_ins = get_irn_arity (call);
357   ir_node *in = NULL;
358
359   for (i = 0; i < n_ins; i ++) {
360     in = get_irn_n (call, i);
361
362     if (mode_P == get_irn_mode (in)) {
363       fprintf (stdout, "--> IN CALL Node (%ld) (%s)\n",
364                get_irn_node_nr (in),
365                get_op_name (get_irn_op (in)));
366     }
367   }
368 }
369 # endif /* defined UNSINN */
370
371 static void pto_node_ret (ir_node *ret, void *env)
372 {
373   /*
374     pto for return node
375
376     so far:
377     input should be availlable
378     todo:
379     just copy
380   */
381
382   if (mode_P == get_irn_mode (ret)) {
383     ir_node *ret_in = get_Return_res_arr (ret) [0];
384
385     pto_t *ret_pto = compute_pto (ret_in, env);
386
387     set_pto (ret, ret_pto);
388   } else {
389     /* set_pto (ret, NULL); */
390     /* nothing! */
391   }
392 }
393
394 static void pto_node_phi (ir_node *phi, void *env)
395 {
396   /*
397     pto for phi node
398
399     so far:
400     all ins present (or?)
401     todo:
402
403   */
404
405   int i;
406   int n_ins = get_irn_arity (phi);
407   ir_node *in = NULL;
408
409   if (mode_P != get_irn_mode (phi)) {
410     return;
411   }
412
413   for (i = 0; i < n_ins; i ++) {
414     in = get_irn_n (phi, i);
415
416     pto_t *in_pto = compute_pto (in, env);
417
418     fprintf (stdout, "--> IN PHI Node (%ld) (%s) (pto = 0x%08x)\n",
419              get_irn_node_nr (in),
420              get_op_name (get_irn_op (in)),
421              (int) in_pto);
422
423     /* must 'merge', but just set something now: */
424     set_pto (phi, in_pto);
425   }
426
427 }
428
429 static void pto_node_cnst (ir_node *cnst, void *env)
430 {
431   /*
432     pto for const node
433
434     so far:
435
436     todo:
437     if this represents something nameable, name it
438   */
439   pto_t *cnst_pto = new_pto ();
440
441
442   set_pto (cnst, cnst_pto);
443 }
444
445 static void pto_node_sym_cnst (ir_node *sym_cnst, void *env)
446 {
447   /*
448     pto for const node
449
450     so far:
451
452     todo:
453     if this represents something nameable, name it
454   */
455   pto_t *sym_cnst_pto = new_pto ();
456
457
458   set_pto (sym_cnst, sym_cnst_pto);
459 }
460
461
462 /*
463   Take care of a single node.  Basically a multiplex/dispatch for the
464   different node types.
465 */
466 static void pto_node (ir_node *node, void *env)
467 {
468   const opcode op = get_irn_opcode (node);
469
470   if (verbose) {
471     fprintf (stdout, "-> Node (%ld) (%s)\n",
472              get_irn_node_nr (node),
473              get_op_name (get_irn_op (node)));
474   }
475
476   switch (op) {
477   case (iro_Start): {
478     /* pto_node_start (node, env); */
479     /* nothing to do */
480
481   } break;
482   case (iro_Load): {
483     pto_node_load (node, env);
484
485   } break;
486   case (iro_Store): {
487     pto_node_store (node, env);
488
489   } break;
490   case (iro_Alloc): {
491     pto_node_alloc (node, env);
492
493   } break;
494   case (iro_Free): {
495     pto_node_free (node, env);
496
497   } break;
498   case (iro_Raise): {
499     pto_node_raise (node, env);
500
501   } break;
502   case (iro_Sel): {
503     pto_node_sel (node, env);
504
505   } break;
506   case (iro_Call): {
507     assert (0 && "calls must be handled in main loop");
508     /* pto_node_call (node, env); */
509     /* also, we should at best look at the ProjV hanging off a call */
510
511   } break;
512   case (iro_Return): {
513     if (0 < get_Return_n_ress (node)) {
514       pto_node_ret (node, env);
515     }
516   } break;
517   case (iro_Proj): {
518     pto_node_proj (node, env);
519   } break;
520   case (iro_Phi): {
521     pto_node_phi (node, env);
522   } break;
523   case (iro_Const): {
524     pto_node_cnst (node, env);
525   } break;
526   case (iro_SymConst): {
527     pto_node_sym_cnst (node, env);
528   } break;
529   case (iro_Cast): {
530     pto_t *cast_pto = compute_pto (get_Cast_op (node), env);
531     set_pto (node, cast_pto);
532   } break;
533   case (iro_Div):
534   case (iro_Quot):
535   case (iro_Mod):
536   case (iro_DivMod):
537     set_pto (node, NULL);
538     break;
539   default: {
540     fprintf (stdout, "%s: not handled: node[%li].op = %s\n",
541              __FUNCTION__,
542              get_irn_node_nr (node),
543              get_op_name (get_irn_op (node)));
544     assert (0 && "something not handled");
545   }
546   }
547 }
548
549 static void pto_node_post (ir_node *node, void *env)
550 {
551   const opcode op = get_irn_opcode (node);
552
553
554   if (iro_Call == op) {
555     ir_node *call = node;
556     entity *ent = NULL;
557     type *ent_tp = NULL;
558     ir_graph *graph = NULL;
559     ir_node *ptr = get_Call_ptr (call);
560
561     if (verbose) {
562       fprintf (stdout, "POST MEM Call Node (%ld)\n",
563                get_irn_node_nr (call));
564     }
565
566     if (iro_Sel == get_irn_opcode (ptr)) {
567       ent = get_Sel_entity (ptr);
568     } else if (iro_SymConst == get_irn_opcode (ptr)) {
569       if (get_SymConst_kind(ptr) == symconst_addr_ent) {
570         ent = get_SymConst_entity (ptr);
571       }
572     }
573
574     assert (NULL != ent && "No ent to call");
575
576     /* Todo:  Iterate over all graphs in 'get_implementing_graphs' */
577     graph = get_entity_irg (ent);
578     if (NULL != graph) {
579       const char *ent_name = (char*) get_entity_name (ent);
580       const char *own_name = (char*) get_type_name (get_entity_owner (ent));
581
582       if (! get_irg_is_mem_visited (graph)) {
583         if (verbose) {
584           fprintf (stdout, " -> visit  graph (0x%08x) of \"%s.%s\"\n",
585                    (int) graph,
586                    own_name,
587                    ent_name);
588         }
589
590         if (TRUE) {
591           ent_tp = get_entity_type (ent);
592           const long n_args =
593             get_method_n_params (ent_tp);
594           ir_node **args = find_irg_args (graph);
595           int i;
596
597           const int n_call_args = get_irn_arity (call);
598
599           assert (n_call_args == n_call_args);
600
601           /* Set args for graph */
602
603           for (i = 0; i < n_args; i ++) {
604             if (NULL != args [i]) {
605               if (mode_P == get_irn_mode (args [i])) {
606                 pto_t *arg_pto = compute_pto (get_irn_n (call, i+1), env);
607                 /* off-by-one because of ProjT bd */
608                 set_pto (args [i], arg_pto);
609               } else {
610                 /* set_pto (args [i], NULL); */
611                 /* nothing */
612               }
613             }
614           }
615           free (args);
616         }
617
618         irg_walk_mem (graph, NULL, pto_node_post, NULL);
619
620         /* maybe get result from called graph */
621         if (0 != get_method_n_ress (ent_tp)) {
622           type *ent_ret_tp = get_method_res_type (ent_tp, 0);
623
624           if (mode_P == get_type_mode (ent_ret_tp)) {
625             pto_t *res_pto = get_pto (get_irg_end (graph));
626             set_pto (call, res_pto);
627           }
628         } else {
629           fprintf (stdout, "%s:%i: no return value for \"%s.%s\"\n",
630                    __FUNCTION__, __LINE__,
631                    get_type_name (get_entity_owner (ent)),
632                    get_entity_name (ent));
633         }
634       }
635     } else {
636       if (verbose) {
637         fprintf (stdout, "%s:%i: Warning: no graph for ent \"%s.%s\"\n",
638                  __FUNCTION__, __LINE__,
639                  get_type_name (get_entity_owner (ent)),
640                  get_entity_name (ent));
641       }
642     }
643   } else {
644     /* anyway: */
645     pto_node (node, env);
646   }
647 }
648
649 /*
650   Run Pto
651 */
652 void pto_run (int do_verbose)
653 {
654   /* int i; */
655   verbose = do_verbose;
656
657   if (verbose) {
658     fprintf (stdout, "START PTO\n");
659   }
660
661   ir_graph *graph = get_irp_main_irg ();
662
663   if (verbose) {
664     fprintf (stdout, "START GRAPH (0x%08x) of \"%s.%s\"\n",
665              (int) graph,
666              get_type_name (get_entity_owner (get_irg_entity (graph))),
667              get_entity_name (get_irg_entity (graph)));
668   }
669
670   if (TRUE) {
671     pto_t *main_pto = new_pto ();
672     const long n_args =
673       get_method_n_params (get_entity_type (get_irg_entity (graph)));
674     ir_node **args = find_irg_args (graph);
675     int i;
676
677     /*
678       Todo:  Set args for MAIN graph!!!
679     */
680
681     for (i = 0; i < n_args; i ++) {
682       fprintf (stdout, "arg [%i] = %ld\n", i,
683                args [i] ? get_irn_node_nr (args [i]) : -1);
684     }
685     set_pto (args [1], main_pto);
686
687     free (args);
688   }
689
690   irg_walk_mem (graph, NULL, pto_node_post, NULL);
691
692   if (verbose) {
693     fprintf (stdout, "END   GRAPH (0x%08x)\n", (int) graph);
694   }
695
696   if (verbose) {
697     fprintf (stdout, "END   PTO\n");
698   }
699 }
700
701 /*
702   Clean Up
703 */
704 void pto_cleanup ()
705 {
706   /* TODO */
707 }
708
709
710 \f
711 /*
712  * $Log$
713  * Revision 1.3  2004/10/25 11:59:45  liekweg
714  * Copy Only works
715  *
716  * Revision 1.2  2004/10/21 11:09:37  liekweg
717  * Moved memwalk stuf into irmemwalk
718  * Moved lset stuff into lset
719  * Moved typalise stuff into typalise
720  *
721  * Revision 1.1  2004/10/20 14:59:42  liekweg
722  * Added ana2, added ecg and pto
723  *
724  */