5 * File name: ir/ana2/pto.c
9 * Created: Mon 18 Oct 2004
11 * Copyright: (c) 1999-2004 Universität Karlsruhe
12 * Licence: This file is protected by GPL - GNU GENERAL PUBLIC LICENSE.
21 # include "pto_util.h"
22 # include "pto_init.h"
29 /* # include "eset.h" */
37 # include "typewalk.h"
38 # include "irmemwalk.h"
40 # define DBGPRINT(lvl, msg) if (get_pto_verbose () > lvl) { fprintf msg; }
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*);
50 Get the pto infos of a node
52 static pto_t *get_pto (ir_node *node)
56 return ((pto_t*) get_irn_link (node));
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).
65 static pto_t *compute_pto (ir_node *node, void *env)
67 pto_t *node_pto = get_pto (node);
69 if (NULL == node_pto) {
70 DBGPRINT (1, (stdout, "%s: must compute pto for %s[%li]\n",
72 get_op_name (get_irn_op (node)),
73 get_irn_node_nr (node)));
77 node_pto = get_pto (node);
86 Transfer the actual arguments to the given call's formal arguments
88 static void set_call_args (ir_node *call, ir_graph *graph, void *env)
90 ir_node **args = find_irg_args (graph);
93 const int n_call_args = get_irn_arity (call);
95 /* call: M x meth_ptr x Arg x Arg x ... x Arg */
96 /* projT(start): Arg x Arg x ... x Arg */
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);
114 Transfer the return value of a call to the callR node
116 static void get_call_ret (ir_node *call, ir_graph *graph, void *env)
118 entity *ent = get_irg_ent (graph);
119 type *ent_tp = get_entity_type (ent);
121 if (0 != get_method_n_ress (ent_tp)) {
122 type *ent_ret_tp = get_method_res_type (ent_tp, 0);
124 if (mode_P == get_type_mode (ent_ret_tp)) {
125 pto_t *res_pto = get_pto (get_irg_end_block (graph));
127 set_pto (call, res_pto);
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.
137 static void pto_node_proj (ir_node *proj, void *env)
140 pto for proj({proj(start),load,call,alloc,raise?,...}) node
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);
146 DBGPRINT (3, (stdout, "%s: --> Proj[%li] (%s)\n",
148 get_irn_node_nr (proj),
149 get_op_name (get_irn_op (in))));
153 /* nothing (handled by proj(proj)) */
158 if (pn_Load_res == proj_proj) {
159 set_pto (proj, compute_pto (in, env));
161 /* ProjM(load) or ProjX(load) - do nothing */
166 /* ProjM (store) or ProjX (store) - nothing */
170 /* copy from alloc */
171 if (pn_Alloc_res == proj_proj) {
172 set_pto (proj, compute_pto (in, env));
174 /* ProjM(alloc) or ProjX (alloc) -- nothing */
179 /* ProjX (raise), ProjM (raise) -- nothing */
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 */
189 set_pto (proj, call_pto);
190 } else if (pn_Call_P_value_res_base == proj_proj) {
192 assert (0 && "what's with pn_Call_P_value_res_base?");
194 /* ProjX (call) or ProjM_exc (call) -- nothing */
200 const ir_node *in_in = get_Proj_pred (in);
201 const opcode in_in_op = get_irn_opcode (in_in);
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);
211 /* proj(proj(start)) - make sure the arguments are initialised */
212 assert (get_pto (proj));
215 DBGPRINT (1, (stdout, "%s:%i: proj(proj(%s)) not handled\n",
216 __FILE__, __LINE__, get_op_name (get_irn_op (in_in))));
223 /* make sure the input has been analysed */
224 pto_t *cast_pto = compute_pto (in, env);
225 set_pto (proj, cast_pto);
230 fprintf (stderr, "%s: opcode %s of Node %ld not handled\n",
232 get_op_name (get_irn_op (in)),
233 get_irn_node_nr (in));
235 assert (0 && "something not handled");
239 DBGPRINT (2, (stdout, "%s: Proj (%s)\n",
241 get_op_name (get_irn_op (in))));
244 static void pto_node_obj_load (ir_node *load, ir_node *ptr,
245 entity *ent, void *env)
248 pto for obj load node
255 const char *ent_name = (char*) get_entity_name (ent);
256 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
258 DBGPRINT (1, (stdout, "%s for (%s[%li])\n",
260 get_op_name (get_irn_op (ptr)),
261 get_irn_node_nr (ptr)));
262 if (! is_pointer_type (get_entity_type (ent))) {
266 DBGPRINT (2, (stdout, "%s: obj load from ent (0x%08x) \"%s.%s\"\n",
272 pto_t *ptr_objs = compute_pto (ptr, env);
273 qset_t *objs = ptr_objs->objs;
275 pto_t *res = pto_new_empty (load);
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 */
281 obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
283 while (NULL != obj_desc) {
284 qset_t *cnts = pto_lookup (obj_desc, ent);
286 pto_add_all_names (res, cnts);
288 obj_desc = (obj_desc_t*) qset_next (objs);
294 static void pto_node_arr_load (ir_node *load, ir_node *ptr,
295 entity *ent, void *env)
298 pto for array load node
301 load.ptr analysed or can be computed on-the-fly
305 const char *ent_name = (char*) get_entity_name (ent);
306 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
308 /* load from array */
309 DBGPRINT (1, (stdout, "%s for (%s[%li])\n",
311 get_op_name (get_irn_op (ptr)),
312 get_irn_node_nr (ptr)));
314 if (! is_pointer_type (get_entity_type (ent))) {
318 DBGPRINT (2, (stdout, "%s: array load from ent (0x%08x) \"%s.%s\"\n",
324 pto_t *ptr_objs = compute_pto (ptr, env);
325 qset_t *objs = ptr_objs->objs;
326 pto_t *res = pto_new_empty (load);
328 obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
330 while (NULL != obj_desc) {
331 qset_t *cnts = pto_lookup (obj_desc, NULL);
333 pto_add_all_names (res, cnts);
335 obj_desc = (obj_desc_t*) qset_next (objs);
341 static void pto_node_load (ir_node *load, void *env)
347 load.ptr analysed or can be computed on-the-fly
351 ir_node *ptr = get_Load_ptr (load);
352 const opcode op = get_irn_opcode (ptr);
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",
360 get_op_name (get_irn_op (ptr)),
361 get_irn_node_nr (ptr)));
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",
367 get_op_name (get_irn_op (ptr)),
368 get_irn_node_nr (ptr)));
372 ent = get_ptr_ent (ptr);
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);
380 pto_node_obj_load (load, ptr, ent, env);
385 static void pto_node_obj_store (ir_node *store,
392 pto for obj store node
394 so far: ptr analysed or can be computed on-the-fly
400 const char *ent_name = (char*) get_entity_name (ent);
401 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
403 DBGPRINT (1, (stdout, "%s: obj store from ent (0x%08x) \"%s.%s\"\n",
405 (int) ent, own_name, ent_name));
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;
412 obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
414 while (NULL != obj_desc) {
415 qset_t *cnts = pto_lookup (obj_desc, ent);
417 qset_insert_all (cnts, vals);
419 obj_desc = (obj_desc_t*) qset_next (objs);
423 static void pto_node_arr_store (ir_node *store,
430 pto for array store node
432 so far: ptr analysed or can be computed on-the-fly
437 const char *ent_name = (char*) get_entity_name (ent);
438 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
440 DBGPRINT (1, (stdout, "%s: array store from ent (0x%08x) \"%s.%s\"\n",
442 (int) ent, own_name, ent_name));
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;
449 obj_desc_t *obj_desc = (obj_desc_t*) qset_start (objs);
451 while (NULL != obj_desc) {
452 qset_t *cnts = pto_lookup (obj_desc, NULL);
454 qset_insert_all (cnts, vals);
456 obj_desc = (obj_desc_t*) qset_next (objs);
460 static void pto_node_store (ir_node *store, void *env)
465 so far: ptr analysed or can be computed on-the-fly
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);
475 if (mode_P != get_irn_mode (val)) {
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);
483 pto_node_obj_store (store, ptr, ent, val, env);
488 static void pto_node_alloc (ir_node *alloc, void *env)
493 so far: nothing to do
498 type *tp = get_Alloc_type (alloc);
500 pto_t *alloc_pto = pto_new_name (alloc, tp);
501 set_pto (alloc, alloc_pto);
504 static void pto_node_free (ir_node *free, void *env)
509 so far: ptr analysed or can be computed on-the-fly
513 /* still, copy somthing */
514 ir_node *ptr = get_Free_ptr (free);
516 pto_t *ptr_pto = compute_pto (ptr, env);
517 set_pto (free, ptr_pto);
520 static void pto_node_raise (ir_node *raise, void *env)
525 so far: ptr analysed or can be computed on-the-fly
530 /* right now, just copy something */
531 ir_node *ptr = get_Raise_exo_ptr (raise);
533 pto_t *ptr_pto = compute_pto (ptr, env);
535 set_pto (raise, ptr_pto);
538 static void pto_node_sel (ir_node *sel, void *env)
543 so far: input selected or can be computed on-the-fly
545 just copy (the selected entity is used in the load/store)
548 ir_node *sel_in = get_Sel_ptr (sel);
549 pto_t *sel_pto = compute_pto (sel_in, env);
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));
559 set_pto (sel, sel_pto);
562 static void pto_node_call (ir_node *call, void *env)
564 ir_graph *graph = NULL;
565 ir_node *ptr = get_Call_ptr (call);
566 entity *ent = get_ptr_ent (ptr);
568 DBGPRINT (0, (stdout, "%s (%s[%li])\n",
570 get_op_name (get_irn_op (call)),
571 get_irn_node_nr (call)));
574 const char *ent_name = (char*) get_entity_name (ent);
575 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
577 /* Todo: Iterate over all graphs in 'get_implementing_graphs' */
578 graph = get_entity_irg (ent);
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));
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);
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)));
599 static void pto_node_ret (ir_node *ret, void *env)
605 input should be availlable
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);
614 pto_t *ret_pto = compute_pto (ret_in, env);
616 DBGPRINT (4, (stdout, "--> Return Node (%ld) (%s)\n",
617 get_irn_node_nr (ret),
618 get_op_name (get_irn_op (ret))));
620 set_pto (ret, ret_pto);
626 static void pto_node_phi (ir_node *phi, void *env)
632 all ins present or can be computed on-the-fly
638 int n_ins = get_irn_arity (phi);
641 if (mode_P != get_irn_mode (phi)) {
645 assert (0 && "test phi");
647 pto_t *phi_pto = get_pto (phi);
649 if (NULL == phi_pto) {
650 phi_pto = pto_new_empty (phi);
651 set_pto (phi, phi_pto);
654 for (i = 0; i < n_ins; i ++) {
655 in = get_irn_n (phi, i);
657 pto_t *in_pto = compute_pto (in, env);
659 DBGPRINT (1, (stdout, "%s: IN PHI Node (%ld) (%s) (pto = 0x%08x)\n",
661 get_irn_node_nr (in),
662 get_op_name (get_irn_op (in)),
665 qset_insert_all (phi_pto->objs, in_pto->objs);
669 static void pto_node_cnst (ir_node *cnst, void *env)
676 if this represents something nameable, name it
678 type *tp = get_Const_type (cnst);
679 pto_t *cnst_pto = pto_new_name (cnst, tp);
682 set_pto (cnst, cnst_pto);
685 static void pto_node_sym_cnst (ir_node *sym_cnst, void *env)
692 if this represents something nameable, name it
694 type *tp = get_entity_type (get_SymConst_entity (sym_cnst));
696 if (is_class_type (tp)) {
697 pto_t *sym_cnst_pto = pto_new_name (sym_cnst, tp);
699 set_pto (sym_cnst, sym_cnst_pto);
705 static void pto_node_end_block (ir_node *end, void *env)
710 so far: all returns are set or can be computed on-the-fly
712 collect results, set to node.
714 type *tp = get_entity_type (get_irg_entity (get_irn_irg (end)));
716 DBGPRINT (2, (stdout, "%s: End Block (%ld) (%s)\n",
718 get_irn_node_nr (end),
719 get_op_name (get_irn_op (end))));
721 if (0 != get_method_n_ress (tp)) {
722 tp = get_method_res_type (tp, 0);
724 if (mode_P == get_type_mode (tp)) {
726 int n_ins = get_irn_arity (end);
727 pto_t *end_pto = pto_new_name (end, get_pointer_points_to_type (tp));
729 for (i = 0; i < n_ins; i ++) {
730 ir_node *ret = get_irn_n (end, i);
732 pto_t *ret_pto = get_pto (ret);
736 set_pto (end, end_pto);
742 Take care of a single node. Basically a multiplex/dispatch for the
743 different node types.
745 static void pto_node (ir_node *node, void *env)
747 const opcode op = get_irn_opcode (node);
749 DBGPRINT (1, (stdout, "%s (%s[%li])\n",
751 get_op_name (get_irn_op (node)),
752 get_irn_node_nr (node)));
756 /* pto_node_start (node, env); */
761 pto_node_load (node, env);
765 pto_node_store (node, env);
769 pto_node_alloc (node, env);
773 pto_node_free (node, env);
777 pto_node_raise (node, env);
781 pto_node_sel (node, env);
785 /* assert (0 && "calls must be handled in main loop"); */
786 pto_node_call (node, env);
789 if (0 < get_Return_n_ress (node)) {
790 pto_node_ret (node, env);
794 pto_node_proj (node, env);
797 pto_node_phi (node, env);
800 pto_node_cnst (node, env);
802 case (iro_SymConst): {
803 pto_node_sym_cnst (node, env);
806 pto_t *cast_pto = compute_pto (get_Cast_op (node), env);
807 set_pto (node, cast_pto);
811 pto_node_end_block (node, env);
813 /* all the uninteresting stuff */
818 set_pto (node, NULL);
820 /* stopgap measure */
822 DBGPRINT (0, (stdout, "%s: not handled: node[%li].op = %s\n",
824 get_irn_node_nr (node),
825 get_op_name (get_irn_op (node))));
826 assert (0 && "something not handled");
830 static void pto_node_pre (ir_node *node, void *env)
832 DBGPRINT (1, (stdout, "%s (%s[%li])\n",
834 get_op_name (get_irn_op (node)),
835 get_irn_node_nr (node)));
837 pto_init_node (node);
840 static void pto_node_post (ir_node *node, void *env)
842 DBGPRINT (1, (stdout, "%s (%s[%li])\n",
844 get_op_name (get_irn_op (node)),
845 get_irn_node_nr (node)));
847 pto_node (node, env);
850 static int pto_verbose = 0;
853 Helper to pto_init --- clear the link fields of class types
855 static void clear_type_link (type_or_ent *thing, void *__unused)
857 if (is_type (thing)) {
858 type *tp = (type*) thing;
860 if (is_class_type (tp)) {
861 DBGPRINT (4, (stdout, "%s (\"%s\")\n",
862 __FUNCTION__, get_type_name (tp)));
864 set_type_link (tp, NULL);
870 Helper to pto_cleanup --- deallocate the field closure lists and clear the link fields of class types
872 static void free_field_list (type_or_ent *thing, void *__unused)
875 type *tp = (type*) thing;
877 if (is_class_type (tp)) {
878 if (NULL != get_type_link (tp)) {
879 entity **fields = (entity**) get_type_link (tp);
884 set_type_link (tp, NULL);
890 void set_pto (ir_node *node, pto_t *pto)
894 set_irn_link (node, (void*) pto);
897 int get_pto_verbose ()
899 return (pto_verbose);
902 void set_pto_verbose (int verbose)
904 pto_verbose = verbose;
912 type_walk (clear_type_link, NULL, NULL);
919 void pto_run (int do_verbose)
922 set_pto_verbose (do_verbose);
924 DBGPRINT (0, (stdout, "START PTO\n"));
926 ir_graph *graph = get_irp_main_irg ();
928 DBGPRINT (0, (stdout, "START GRAPH (0x%08x) of \"%s.%s\"\n",
930 get_type_name (get_entity_owner (get_irg_entity (graph))),
931 get_entity_name (get_irg_entity (graph))));
933 /* Set args for main graph */
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);
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);
945 for (i = 0; i < n_args; i ++) {
946 DBGPRINT (2, (stdout, "arg [%i] = %s[%ld]\n",
948 args [i] ? get_op_name (get_irn_op (args [i])) : "none",
949 args [i] ? get_irn_node_nr (args [i]) : -1));
951 set_pto (args [1], main_pto);
956 irg_walk_mem (graph, pto_node_pre, pto_node_post, NULL);
958 DBGPRINT (0, (stdout, "END GRAPH (0x%08x)\n", (int) graph));
959 DBGPRINT (0, (stdout, "END PTO\n"));
961 obj_desc_list_all (NULL);
969 type_walk (free_field_list, NULL, NULL);
976 * Revision 1.4 2004/11/04 14:58:38 liekweg
977 * expanded pto, added initialisation, added debugging printing
979 * Revision 1.3 2004/10/25 11:59:45 liekweg
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
987 * Revision 1.1 2004/10/20 14:59:42 liekweg
988 * Added ana2, added ecg and pto