Fix changelog typo.
[official-gcc.git] / gcc / tree-alias-ander.c
blob471a7fd99f30bd74b987371e058f93668bee0593
1 /* Tree based Andersen points-to analysis
2 Copyright (C) 2002, 2003 Free Software Foundation, Inc.
3 Contributed by Daniel Berlin <dberlin@dberlin.org>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "ggc.h"
28 #include "bitmap.h"
29 #include "tree-alias-type.h"
30 #include "tree-alias-ander.h"
31 #include "flags.h"
32 #include "rtl.h"
33 #include "tm_p.h"
34 #include "hard-reg-set.h"
35 #include "basic-block.h"
36 #include "output.h"
37 #include "errors.h"
38 #include "expr.h"
39 #include "diagnostic.h"
40 #include "tree.h"
41 #include "tree-flow.h"
42 #include "tree-inline.h"
43 #include "varray.h"
44 #include "tree-gimple.h"
45 #include "splay-tree.h"
46 #include "engine/util.h"
47 #include "libcompat/regions.h"
48 #include "andersen_terms.h"
49 #include "cgraph.h"
50 #include "tree-pass.h"
53 /* Andersen's interprocedural points-to analysis.
54 This is a flow-insensitive, context insensitive algorithm.
56 This file is an implementation of the alias_ops structure used by
57 tree-alias-common.c to drive PTA analysis.
59 All these functions do is generate constraints for and through
60 libbanshee. When we query for a points-to set, we ask libbanshee
61 to solve the constraints and give us the answer. The terms of the
62 constraints are the aterms, which are an opaque data structure
63 that stores libbanshee specific data for the constraints.
65 The constraints to be generated come from andersen's paper. By
66 constraint, we mean something like "the points-to set of A must be
67 a subset or equal to the points-to set of B" or "the points-to set
68 of A must include Q". In order to avoid having to write all the
69 constraints directly in the code, we use helper functions such as
70 pta_assignment, pta_rvalue, etc, that generate the necessary
71 constraint terms for us, making for much more readable code.
73 One could replace libbanshee with some other constraint solving
74 engine, and you'd simply have to replace the implementation of the
75 pta_* functions, and provide replacements for the aterm specific
76 functions (like making a list of aterms, printing the label of an
77 aterm). However, libbanshee is extremely fast, and extremely low
78 memory usage, so one would be hard pressed to do better than it
79 anyway.
81 Understanding how constraint solving and what each constraint means is
82 beyond the scope of this documentation. See the libbanshee
83 documentation, and references therein for more enlightenment.
85 That said, our constraints inclusion constraints of set
86 expressions. Given the helper functions, the various inference
87 functions we implement should *look* relatively straightforward.
89 In order to save time during queries, we cache the resulting
90 points-to sets of each variable, rather than recalculate them
91 again and again. (libbanshee actually has it's own internal
92 caching, but the function call overhead for calling the solver is
93 non-trivial, given the number of queries).
95 Todo: Don't pass alias ops as first argument, just have a global
96 "current_alias_ops". */
98 static unsigned int id_num = 1;
99 static region andersen_rgn;
100 static void andersen_simple_assign (struct tree_alias_ops *,
101 alias_var, alias_var);
102 static void andersen_addr_assign (struct tree_alias_ops *,
103 alias_var, alias_var);
104 static void andersen_ptr_assign (struct tree_alias_ops *,
105 alias_var, alias_var);
106 static void andersen_op_assign (struct tree_alias_ops *,
107 alias_var, varray_type, tree, bitmap);
108 static void andersen_heap_assign (struct tree_alias_ops *, alias_var);
109 static void andersen_assign_ptr (struct tree_alias_ops *,
110 alias_var, alias_var);
111 static void andersen_function_def (struct tree_alias_ops *, alias_var,
112 varray_type, alias_var);
113 static int andersen_function_call (struct tree_alias_ops *, alias_var,
114 alias_var, varray_type, bitmap);
115 static void andersen_init (struct tree_alias_ops *);
116 static int print_out_result (splay_tree_node, void *);
117 static void andersen_cleanup (struct tree_alias_ops *);
118 static bool andersen_may_alias (struct tree_alias_ops *, alias_var,
119 alias_var);
120 static bool andersen_same_points_to_set (struct tree_alias_ops *,
121 alias_var, alias_var);
122 static bool andersen_empty_points_to_set (struct tree_alias_ops *,
123 alias_var);
124 static alias_var andersen_add_var (struct tree_alias_ops *, tree);
125 static alias_var andersen_add_var_same (struct tree_alias_ops *,
126 tree, alias_var);
127 static bool pointer_destroying_op (tree);
128 static aterm_list get_ptset (alias_var);
129 static splay_tree ptamap;
132 static struct tree_alias_ops andersen_ops = {
133 andersen_init,
134 andersen_cleanup,
135 andersen_add_var,
136 andersen_add_var_same,
137 andersen_simple_assign,
138 andersen_addr_assign,
139 andersen_ptr_assign,
140 andersen_op_assign,
141 andersen_heap_assign,
142 andersen_assign_ptr,
143 andersen_function_def,
144 andersen_function_call,
145 andersen_may_alias,
146 andersen_same_points_to_set,
147 andersen_empty_points_to_set,
148 0, /* data */
149 0, /* Currently non-interprocedural */
150 1 /* Can do IP on all statics without help. */
152 struct tree_alias_ops *andersen_alias_ops = &andersen_ops;
154 static void term_inclusion (aterm, aterm);
155 static void pta_init (void);
156 static void pta_reset (void);
157 static aterm get_ref (aterm);
158 static argterm fun_rec_aterm (aterm_list);
159 static aterm pta_make_lam (const char *, aterm, aterm_list);
160 static aterm pta_make_ref (const char *);
161 static aterm pta_bottom (void);
162 static aterm pta_join (aterm, aterm);
163 static aterm pta_deref (aterm);
164 static aterm pta_rvalue (aterm);
165 static aterm pta_address (aterm);
166 static void pta_assignment (aterm, aterm);
167 static aterm pta_make_fun (const char *, aterm, aterm_list);
168 static aterm pta_application (aterm, aterm_list);
170 typedef aterm contents_type;
171 static contents_type pta_get_contents (aterm);
172 static void pr_ptset_aterm_elem (aterm);
173 static void pta_pr_ptset (contents_type);
175 /* Hook for debugging. This function is called instead of
176 aterm_inclusion, and lets us print the actual constraints as they
177 are generated. */
179 static void
180 term_inclusion (aterm t1, aterm t2)
182 if (dump_file)
184 fprintf (dump_file, "Constraint: ");
185 aterm_print (dump_file, t1);
186 fprintf (dump_file, " <= ");
187 aterm_print (dump_file, t2);
188 fprintf (dump_file, "\n");
191 aterm_inclusion (t1, t2);
194 /* Initialize libbanshee's constraint engine. */
196 static void
197 pta_init (void)
199 andersen_terms_init ();
202 /* Reset libbanshee's constraint engine. We do this when we are done
203 using it, as it releases the memory libbanshee is using. */
205 static void
206 pta_reset (void)
208 andersen_terms_reset ();
211 static aterm
212 get_ref (aterm t)
214 struct ref_decon r_decon;
215 r_decon = ref_decon (t);
217 assert (r_decon.f1);
219 return r_decon.f1;
222 /* Make a function record out of the arguments. */
224 static argterm
225 fun_rec_aterm (aterm_list args)
227 region scratch;
228 int counter = 0;
229 argterm rest, result;
230 aterm_list_scanner scan;
231 aterm temp;
232 char field_name[512];
233 argterm_map map;
235 scratch = newregion ();
236 map = new_argterm_map (scratch);
237 aterm_list_scan (args, &scan);
238 while (aterm_list_next (&scan, &temp))
240 snprintf (field_name, 512, "%d", counter++);
241 argterm_map_cons (argterm_make_field (field_name, temp), map);
244 rest = argterm_wild ();
245 /* rest = argterm_fresh(); */
247 /* safe since field_add makes a copy of the string*/
248 result = argterm_row (map, rest);
250 deleteregion (scratch);
252 return result;
256 static aterm
257 pta_make_lam (const char *id, aterm ret, aterm_list args)
259 return lam (label_term_constant (id), fun_rec_aterm (args), ret);
262 /* Make a label reference to the given id. */
264 static aterm
265 pta_make_ref (const char *id)
268 aterm var = aterm_fresh (id);
270 label_term tag = label_term_constant (id);
272 return ref (tag, var, var);
275 /* Return the empty set. */
277 static aterm
278 pta_bottom (void)
280 return aterm_zero ();
283 /* Join two terms, such that anything in set t1 will also be in set
284 t2, and vice versa. */
286 static aterm
287 pta_join (aterm t1, aterm t2)
289 aterm result;
290 region scratch_rgn = newregion ();
291 aterm_list list = new_aterm_list (scratch_rgn);
293 aterm_list_cons (t1, list);
294 aterm_list_cons (t2, list);
297 result = aterm_union (list);
298 deleteregion (scratch_rgn);
300 return result;
303 /* Generate the constraint for a dereference of term t1. */
305 static aterm
306 pta_deref (aterm t1)
308 return ref_proj2 (t1);
311 /* Generate the constraint for t1 being an rvalue. */
313 static aterm
314 pta_rvalue (aterm t1)
316 return pta_deref (t1);
319 /* Generate the constraint for taking the address of t1. */
321 static aterm
322 pta_address (aterm t1)
324 return ref (label_term_one (), aterm_one (), t1);
327 /* Generate the constraint for assigning t2 to t1. */
329 static void
330 pta_assignment (aterm t1, aterm t2)
332 term_inclusion (t1, ref_pat1 (t2));
335 /* Make a function from the given name, return value, and arguments. */
337 static aterm
338 pta_make_fun (const char *name, aterm ret, aterm_list args)
340 aterm temp;
341 aterm_list_scanner scan;
342 region scratch_rgn = newregion ();
343 aterm_list arg_list = new_aterm_list (scratch_rgn);
345 aterm_list_scan (args, &scan);
347 while (aterm_list_next (&scan, &temp))
349 aterm_list_cons (get_ref (temp), arg_list);
352 return pta_make_lam (name, get_ref (ret), arg_list);
355 /* Return the constraint for calling function T with arguments
356 ACTUALS. */
358 static aterm
359 pta_application (aterm t, aterm_list actuals)
361 argterm args = fun_rec_aterm (actuals);
363 term_inclusion (t, lam_pat1 (args));
364 return pta_address (lam_proj2 (t));
367 /* Return the contents of set expression T. */
369 static contents_type
370 pta_get_contents (aterm t)
372 struct ref_decon t_decon;
373 t_decon = ref_decon (t);
375 return t_decon.f1;
378 /* Print out a points-to set element. */
380 static void
381 pr_ptset_aterm_elem (aterm t)
383 struct ref_decon ref;
384 struct lam_decon lam;
386 ref = ref_decon (t);
387 lam = lam_decon (t);
389 fprintf (dump_file, ",");
390 if (ref.f0)
391 label_term_print (dump_file, ref.f0);
392 else if (lam.f0)
393 label_term_print (dump_file, lam.f0);
397 /* Print out a points-to set. */
399 static void
400 pta_pr_ptset (contents_type t)
402 int size;
403 region scratch_rgn;
404 aterm_list ptset;
405 scratch_rgn = newregion ();
406 ptset = aterm_list_copy (scratch_rgn, aterm_tlb (t));
408 size = aterm_list_length (ptset);
410 fprintf (dump_file, "{");
411 if (!aterm_list_empty (ptset))
413 struct ref_decon ref;
414 struct lam_decon lam;
415 ref = ref_decon (aterm_list_head (ptset));
416 lam = lam_decon (aterm_list_head (ptset));
417 if (ref.f0)
418 label_term_print (dump_file, ref.f0);
419 else if (lam.f0)
420 label_term_print (dump_file, lam.f0);
422 /* aterm_pr(stdout,aterm_hd(ptset)); */
423 ptset = aterm_list_tail (ptset);
425 aterm_list_app (ptset, pr_ptset_aterm_elem);
426 fprintf (dump_file, "}(%d)\n", size);
427 deleteregion (scratch_rgn);
430 /* Initialize Andersen alias analysis. */
431 static int initted = 0;
433 static void
434 andersen_init (struct tree_alias_ops *ops ATTRIBUTE_UNUSED)
436 #if 0
437 /* Don't claim we can do ip partial unless we have unit_at_a_time on. */
438 if (!flag_unit_at_a_time)
439 #endif
440 andersen_ops.ip_partial = 0;
441 if (!initted || (!andersen_ops.ip_partial && !andersen_ops.ip))
443 pta_init ();
444 andersen_rgn = newregion ();
445 initted = 1;
448 ptamap = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
452 static int
453 print_out_result (splay_tree_node node, void *data ATTRIBUTE_UNUSED)
455 fprintf (dump_file, "%s :=",
456 alias_get_name (ALIAS_VAR_DECL (((alias_var) node->value))));
457 pta_pr_ptset (pta_get_contents ((aterm) node->key));
458 return 0;
461 /* Cleanup after Andersen alias analysis. */
463 static void
464 andersen_cleanup (struct tree_alias_ops *ops ATTRIBUTE_UNUSED)
466 if (dump_file)
468 if (dump_flags & TDF_STATS)
470 fprintf (dump_file, "\nPoints-to stats:\n");
471 andersen_terms_stats (dump_file);
474 fprintf (dump_file, "\nPoints-to sets:\n");
475 splay_tree_foreach (ptamap, print_out_result, NULL);
478 splay_tree_delete (ptamap);
480 if (!andersen_ops.ip_partial && !andersen_ops.ip)
482 pta_reset ();
483 deleteregion (andersen_rgn);
484 andersen_rgn = NULL;
488 /* Add decl to the analyzer, and return a var for it. For
489 Andersen, we create a new alias var for the declaration, and
490 return that. */
492 static alias_var
493 andersen_add_var (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, tree decl)
495 alias_var ret;
496 if (dump_file && (dump_flags & TDF_DETAILS))
497 fprintf (dump_file, "Adding variable %s\n",
498 alias_get_name (decl));
500 if (alias_get_name (decl) != NULL)
502 ret = alias_var_new_with_aterm (decl,
503 pta_make_ref (alias_get_name (decl)));
505 else
507 char *tmp_name;
508 ASM_FORMAT_PRIVATE_NAME (tmp_name, "unnamed var", id_num++);
509 ret = alias_var_new_with_aterm (decl, pta_make_ref (tmp_name));
511 splay_tree_insert (ptamap, (splay_tree_key) ALIAS_VAR_ATERM (ret),
512 (splay_tree_value) ret);
513 ALIAS_VAR_PTSET (ret) = NULL;
515 return ret;
518 /* Add a variable to the analyzer that is equivalent (as far as
519 aliases go) to some existing alias variable.
520 For Andersen, we just call a function that does this for us. */
522 static alias_var
523 andersen_add_var_same (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, tree decl,
524 alias_var tv)
526 alias_var ret;
528 if (dump_file && (dump_flags & TDF_DETAILS))
529 fprintf (dump_file, "Adding variable %s same as %s\n",
530 alias_get_name (decl), alias_get_name (ALIAS_VAR_DECL (tv)));
532 if (alias_get_name (decl) != NULL)
533 ret = alias_var_new_with_aterm (decl,
534 pta_make_ref (alias_get_name (decl)));
535 else
537 char *tmp_name;
538 ASM_FORMAT_PRIVATE_NAME (tmp_name, "unnamed var", id_num++);
539 ret = alias_var_new_with_aterm (decl, pta_make_ref (tmp_name));
542 pta_join (ALIAS_VAR_ATERM (tv), ALIAS_VAR_ATERM (ret));
543 splay_tree_insert (ptamap, (splay_tree_key) ALIAS_VAR_ATERM (ret),
544 (splay_tree_value) ret);
545 ALIAS_VAR_PTSET (tv) = NULL;
546 ALIAS_VAR_PTSET (ret) = NULL;
548 return ret;
551 /* Inference for simple assignment (lhs = rhs) */
553 static void
554 andersen_simple_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
555 alias_var lhs, alias_var rhs)
557 if (dump_file && (dump_flags & TDF_DETAILS))
558 fprintf (dump_file, "Simple assignment %s = %s\n",
559 alias_get_name (ALIAS_VAR_DECL (lhs)),
560 alias_get_name (ALIAS_VAR_DECL (rhs)));
561 if (lhs == rhs)
562 return;
564 /* The rvalue is just the term itself, and we generate a constraint
565 for assigning it to the lhs. */
566 pta_assignment (ALIAS_VAR_ATERM (lhs),
567 pta_rvalue (ALIAS_VAR_ATERM (rhs)));
570 /* Inference for address assignment (lhs = &addr) */
572 static void
573 andersen_addr_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
574 alias_var lhs, alias_var addr)
576 if (addr == NULL)
577 return;
578 if (dump_file && (dump_flags & TDF_DETAILS))
579 fprintf (dump_file, "Address assignment %s = &%s\n",
580 alias_get_name (ALIAS_VAR_DECL (lhs)),
581 alias_get_name (ALIAS_VAR_DECL (addr)));
583 /* The rvalue here is the address of a term, and we generate a
584 constraint to assign this address to the lhs. */
585 pta_assignment (ALIAS_VAR_ATERM (lhs),
586 pta_rvalue (pta_address (ALIAS_VAR_ATERM (addr))));
590 /* Inference for pointer assignment (lhs = *ptr) */
592 static void
593 andersen_ptr_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
594 alias_var lhs, alias_var ptr)
597 if (ptr == NULL)
598 return;
599 if (dump_file && (dump_flags & TDF_DETAILS))
600 fprintf (dump_file, "Pointer assignment %s = *%s\n",
601 alias_get_name (ALIAS_VAR_DECL (lhs)),
602 alias_get_name (ALIAS_VAR_DECL (ptr)));
604 pta_assignment (ALIAS_VAR_ATERM (lhs),
605 pta_rvalue (pta_deref (ALIAS_VAR_ATERM (ptr))));
609 /* Determine if OP destroys the current assumed to be valid pointer
610 (whether it generates a new valid pointer is not relevant). */
612 static bool
613 pointer_destroying_op (tree op)
615 switch (TREE_CODE (op))
617 case TRUTH_AND_EXPR:
618 case TRUTH_OR_EXPR:
619 case TRUTH_NOT_EXPR:
620 case LT_EXPR:
621 case GT_EXPR:
622 case GE_EXPR:
623 case LE_EXPR:
624 case EQ_EXPR:
625 case NE_EXPR:
626 case MULT_EXPR:
627 case TRUNC_DIV_EXPR:
628 case LSHIFT_EXPR:
629 case RSHIFT_EXPR:
630 case LROTATE_EXPR:
631 case RROTATE_EXPR:
632 return true;
633 default:
634 return false;
636 return false;
639 /* Inference rule for operations (lhs = operation(operands)). */
641 static void
642 andersen_op_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
643 alias_var lhs, varray_type operands, tree operation,
644 bitmap addrargs)
646 aterm newvar = NULL;
648 if (VARRAY_ACTIVE_SIZE (operands) == 0)
649 return;
651 if (dump_file && (dump_flags & TDF_DETAILS))
653 fprintf (dump_file, "Op assignment %s = ",
654 alias_get_name (ALIAS_VAR_DECL (lhs)));
655 print_generic_stmt (dump_file, operation, dump_flags);
656 fprintf (dump_file, "\n");
660 /* Pointer destroying operations do not give us the same valid pointer
661 back, and thus, are assignment to pta_bottom. */
662 if (pointer_destroying_op (operation))
664 pta_assignment (ALIAS_VAR_ATERM (lhs), pta_rvalue (pta_bottom ()));
665 return;
668 /* Operations in general we can't track the exact effect of. Thus,
669 we conservatively assume that it could make the LHS point to
670 *anything* the RHS points to. To signify this, we join the RHS
671 variables together and assign it to the LHS. */
672 /* The >2 case occurs when we are dealing with constructors. */
673 if (VARRAY_ACTIVE_SIZE (operands) > 2)
675 size_t i;
676 alias_var tv1 = VARRAY_GENERIC_PTR (operands, 0);
677 newvar = ALIAS_VAR_ATERM (tv1);
678 for (i = 1; i < VARRAY_ACTIVE_SIZE (operands); i++)
680 alias_var tempvar = VARRAY_GENERIC_PTR (operands, i);
681 aterm t2 = ALIAS_VAR_ATERM (tempvar);
682 if (bitmap_bit_p (addrargs, i))
683 newvar = pta_join (newvar, pta_address (t2));
684 else
685 newvar = pta_join (newvar, t2);
688 else if (VARRAY_ACTIVE_SIZE (operands) == 2)
690 alias_var tv1 = VARRAY_GENERIC_PTR (operands, 0);
691 alias_var tv2 = VARRAY_GENERIC_PTR (operands, 1);
692 aterm t1 = ALIAS_VAR_ATERM (tv1);
693 aterm t2 = ALIAS_VAR_ATERM (tv2);
694 if (bitmap_bit_p (addrargs, 0) && bitmap_bit_p (addrargs, 1))
695 newvar = pta_join (pta_address (t1), pta_address (t2));
696 else if (bitmap_bit_p (addrargs, 0))
697 newvar = pta_join (pta_address (t1), t2);
698 else if (bitmap_bit_p (addrargs, 1))
699 newvar = pta_join (t1, pta_address (t2));
700 else
701 newvar = pta_join (t1, t2);
703 else if (VARRAY_ACTIVE_SIZE (operands) == 1)
705 alias_var tv1 = VARRAY_GENERIC_PTR (operands, 0);
706 aterm t1 = ALIAS_VAR_ATERM (tv1);
707 if (bitmap_bit_p (addrargs, 0))
708 newvar = pta_address (t1);
709 else
710 newvar = t1;
712 pta_assignment (ALIAS_VAR_ATERM (lhs), pta_rvalue (newvar));
715 /* Inference for heap assignment (lhs = alloc). */
717 static void
718 andersen_heap_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
719 alias_var lhs ATTRIBUTE_UNUSED)
721 #if 0
722 alias_type type1;
723 ECR tau;
724 type1 = ECR_get_type (alias_var_get_ECR (lhs));
725 tau = alias_ltype_loc (type1);
727 if (ECR_get_type (tau) == alias_bottom)
728 ECR_set_type (tau, alias_ltype_new ());
729 #endif
732 /* Inference for assignment to a pointer (*ptr = rhs). */
734 static void
735 andersen_assign_ptr (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
736 alias_var ptr, alias_var rhs)
739 if (rhs == NULL)
740 return;
741 if (dump_file && (dump_flags & TDF_DETAILS))
742 fprintf (dump_file, "Assignment to pointer *%s = %s\n",
743 alias_get_name (ALIAS_VAR_DECL (ptr)),
744 alias_get_name (ALIAS_VAR_DECL (rhs)));
745 /* The RHS is a standard rvalue, and the LHS is a pointer
746 dereference. */
747 pta_assignment (pta_deref (ALIAS_VAR_ATERM (ptr)),
748 pta_rvalue (ALIAS_VAR_ATERM (rhs)));
751 /* Inference for a function definition. */
753 static void
754 andersen_function_def (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
755 alias_var func, varray_type params,
756 alias_var retval)
758 aterm_list args = new_aterm_list (andersen_rgn);
759 aterm fun_type;
761 size_t l = VARRAY_ACTIVE_SIZE (params);
762 size_t i;
764 /* Set up the arguments for the new function type. */
765 for (i = 0; i < l; i++)
767 alias_var tv = VARRAY_GENERIC_PTR (params, i);
768 aterm_list_cons (ALIAS_VAR_ATERM (tv), args);
770 /* Create the function type. */
771 fun_type = pta_make_fun (alias_get_name (ALIAS_VAR_DECL (func)),
772 ALIAS_VAR_ATERM (retval), args);
774 /* Assign the function type itself to the function. */
775 pta_assignment (ALIAS_VAR_ATERM (func), fun_type);
778 /* Inference for a function call assignment. */
780 static int
781 andersen_function_call (struct tree_alias_ops *ops,
782 alias_var lhs, alias_var func,
783 varray_type args, bitmap addrargs)
785 aterm_list actuals = new_aterm_list (andersen_rgn);
786 aterm ftype = ALIAS_VAR_ATERM (func);
787 aterm ret = NULL;
788 aterm res;
789 tree decl = ALIAS_VAR_DECL (func);
791 size_t i;
793 if (lhs)
794 ret = ALIAS_VAR_ATERM (lhs);
795 for (i = 0; i < VARRAY_ACTIVE_SIZE (args); i++)
797 alias_var argtv = VARRAY_GENERIC_PTR (args, i);
798 aterm arg = ALIAS_VAR_ATERM (argtv);
799 if (bitmap_bit_p (addrargs, i))
800 aterm_list_cons (pta_rvalue (pta_address (arg)), actuals);
801 else
802 aterm_list_cons (pta_rvalue (arg), actuals);
804 aterm_list_reverse (actuals);
806 /* Generate the constraint that calls the function with it's
807 arguments, and gives us the result. This in turn applies
808 whatever constraints are in that function. */
809 res = pta_application (pta_rvalue (ftype), actuals);
810 /* We only need care about the result if we have an LHS. If we do,
811 assign the result of function application back to the LHS. */
812 if (ret)
813 pta_assignment (ret, pta_rvalue (res));
815 /* We can handle functions we've got trees for. non-statics will
816 just have incoming parameters assigned to global_var if
817 necessary. */
818 if (TREE_CODE (decl) == FUNCTION_DECL
819 && DECL_PTA_ALIASVAR (decl)
820 && ops->ip_partial
821 && (cgraph_local_info (decl)->local))
823 return 0;
825 return 1;
829 /* Simple pointer comparison function for list sorting. */
831 static int
832 simple_cmp (const aterm a, const aterm b)
834 return (int *)a - (int *)b;
838 /* Get the points-to set for TV, caching if it we had to compute it. */
840 static aterm_list
841 get_ptset (alias_var tv)
843 aterm_list ptset;
844 ptset = ALIAS_VAR_PTSET (tv);
845 if (ptset != NULL)
846 return ptset;
847 ptset = aterm_tlb (pta_get_contents (ALIAS_VAR_ATERM (tv)));
848 ALIAS_VAR_PTSET (tv) = ptset;
849 return ptset;
853 /* Determine if two aterm's have the same points-to set. */
855 static bool
856 andersen_same_points_to_set (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
857 alias_var ptrtv, alias_var vartv)
859 aterm_list ptset1, ptset2;
860 aterm_list_scanner scan1, scan2;
861 aterm data1, data2;
862 region scratch_rgn = newregion ();
864 ptset1 = get_ptset (ptrtv);
865 ptset2 = get_ptset (vartv);
867 if (aterm_list_length (ptset1) != aterm_list_length (ptset2))
869 deleteregion (scratch_rgn);
870 return false;
873 if (ptset1 == ptset2)
875 deleteregion (scratch_rgn);
876 return true;
879 ptset1 = aterm_list_copy (scratch_rgn, ptset1);
880 ptset2 = aterm_list_copy (scratch_rgn, ptset2);
882 if (aterm_list_length (ptset1) != aterm_list_length (ptset2))
884 deleteregion (scratch_rgn);
885 return false;
888 ptset1 = aterm_list_sort (ptset1, simple_cmp);
889 ptset2 = aterm_list_sort (ptset2, simple_cmp);
891 aterm_list_scan (ptset1, &scan1);
892 aterm_list_scan (ptset2, &scan2);
893 while (aterm_list_next (&scan1, &data1))
895 aterm_list_next (&scan2, &data2);
896 if (data1 != data2)
898 deleteregion(scratch_rgn);
899 return false;
902 deleteregion(scratch_rgn);
903 return true;
907 /* Determine if two variables may alias. In our case, this means
908 whether the decl represented by PTRTV can point to VARTV. */
910 static bool
911 andersen_may_alias (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
912 alias_var ptrtv, alias_var vartv)
914 aterm_list ptset;
915 ptset = get_ptset (ptrtv);
917 if (aterm_list_empty (ptset))
918 return false;
920 return aterm_list_member (ptset, ALIAS_VAR_ATERM (vartv));
923 /* Determine whether PTRTV has an empty points-to set. IE it may not
924 point to anything. */
926 static bool
927 andersen_empty_points_to_set (struct tree_alias_ops *ops ATTRIBUTE_UNUSED,
928 alias_var ptrtv)
930 aterm_list ptset;
931 ptset = get_ptset (ptrtv);
932 return aterm_list_empty (ptset);