diff options
Diffstat (limited to 'gcc/tree-alias-ander.c')
-rw-r--r-- | gcc/tree-alias-ander.c | 933 |
1 files changed, 0 insertions, 933 deletions
diff --git a/gcc/tree-alias-ander.c b/gcc/tree-alias-ander.c deleted file mode 100644 index 471a7fd99f3..00000000000 --- a/gcc/tree-alias-ander.c +++ /dev/null @@ -1,933 +0,0 @@ -/* Tree based Andersen points-to analysis - Copyright (C) 2002, 2003 Free Software Foundation, Inc. - Contributed by Daniel Berlin <dberlin@dberlin.org> - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "ggc.h" -#include "bitmap.h" -#include "tree-alias-type.h" -#include "tree-alias-ander.h" -#include "flags.h" -#include "rtl.h" -#include "tm_p.h" -#include "hard-reg-set.h" -#include "basic-block.h" -#include "output.h" -#include "errors.h" -#include "expr.h" -#include "diagnostic.h" -#include "tree.h" -#include "tree-flow.h" -#include "tree-inline.h" -#include "varray.h" -#include "tree-gimple.h" -#include "splay-tree.h" -#include "engine/util.h" -#include "libcompat/regions.h" -#include "andersen_terms.h" -#include "cgraph.h" -#include "tree-pass.h" - - -/* Andersen's interprocedural points-to analysis. - This is a flow-insensitive, context insensitive algorithm. - - This file is an implementation of the alias_ops structure used by - tree-alias-common.c to drive PTA analysis. - - All these functions do is generate constraints for and through - libbanshee. When we query for a points-to set, we ask libbanshee - to solve the constraints and give us the answer. The terms of the - constraints are the aterms, which are an opaque data structure - that stores libbanshee specific data for the constraints. - - The constraints to be generated come from andersen's paper. By - constraint, we mean something like "the points-to set of A must be - a subset or equal to the points-to set of B" or "the points-to set - of A must include Q". In order to avoid having to write all the - constraints directly in the code, we use helper functions such as - pta_assignment, pta_rvalue, etc, that generate the necessary - constraint terms for us, making for much more readable code. - - One could replace libbanshee with some other constraint solving - engine, and you'd simply have to replace the implementation of the - pta_* functions, and provide replacements for the aterm specific - functions (like making a list of aterms, printing the label of an - aterm). However, libbanshee is extremely fast, and extremely low - memory usage, so one would be hard pressed to do better than it - anyway. - - Understanding how constraint solving and what each constraint means is - beyond the scope of this documentation. See the libbanshee - documentation, and references therein for more enlightenment. - - That said, our constraints inclusion constraints of set - expressions. Given the helper functions, the various inference - functions we implement should *look* relatively straightforward. - - In order to save time during queries, we cache the resulting - points-to sets of each variable, rather than recalculate them - again and again. (libbanshee actually has it's own internal - caching, but the function call overhead for calling the solver is - non-trivial, given the number of queries). - - Todo: Don't pass alias ops as first argument, just have a global - "current_alias_ops". */ - -static unsigned int id_num = 1; -static region andersen_rgn; -static void andersen_simple_assign (struct tree_alias_ops *, - alias_var, alias_var); -static void andersen_addr_assign (struct tree_alias_ops *, - alias_var, alias_var); -static void andersen_ptr_assign (struct tree_alias_ops *, - alias_var, alias_var); -static void andersen_op_assign (struct tree_alias_ops *, - alias_var, varray_type, tree, bitmap); -static void andersen_heap_assign (struct tree_alias_ops *, alias_var); -static void andersen_assign_ptr (struct tree_alias_ops *, - alias_var, alias_var); -static void andersen_function_def (struct tree_alias_ops *, alias_var, - varray_type, alias_var); -static int andersen_function_call (struct tree_alias_ops *, alias_var, - alias_var, varray_type, bitmap); -static void andersen_init (struct tree_alias_ops *); -static int print_out_result (splay_tree_node, void *); -static void andersen_cleanup (struct tree_alias_ops *); -static bool andersen_may_alias (struct tree_alias_ops *, alias_var, - alias_var); -static bool andersen_same_points_to_set (struct tree_alias_ops *, - alias_var, alias_var); -static bool andersen_empty_points_to_set (struct tree_alias_ops *, - alias_var); -static alias_var andersen_add_var (struct tree_alias_ops *, tree); -static alias_var andersen_add_var_same (struct tree_alias_ops *, - tree, alias_var); -static bool pointer_destroying_op (tree); -static aterm_list get_ptset (alias_var); -static splay_tree ptamap; - - -static struct tree_alias_ops andersen_ops = { - andersen_init, - andersen_cleanup, - andersen_add_var, - andersen_add_var_same, - andersen_simple_assign, - andersen_addr_assign, - andersen_ptr_assign, - andersen_op_assign, - andersen_heap_assign, - andersen_assign_ptr, - andersen_function_def, - andersen_function_call, - andersen_may_alias, - andersen_same_points_to_set, - andersen_empty_points_to_set, - 0, /* data */ - 0, /* Currently non-interprocedural */ - 1 /* Can do IP on all statics without help. */ -}; -struct tree_alias_ops *andersen_alias_ops = &andersen_ops; - -static void term_inclusion (aterm, aterm); -static void pta_init (void); -static void pta_reset (void); -static aterm get_ref (aterm); -static argterm fun_rec_aterm (aterm_list); -static aterm pta_make_lam (const char *, aterm, aterm_list); -static aterm pta_make_ref (const char *); -static aterm pta_bottom (void); -static aterm pta_join (aterm, aterm); -static aterm pta_deref (aterm); -static aterm pta_rvalue (aterm); -static aterm pta_address (aterm); -static void pta_assignment (aterm, aterm); -static aterm pta_make_fun (const char *, aterm, aterm_list); -static aterm pta_application (aterm, aterm_list); - -typedef aterm contents_type; -static contents_type pta_get_contents (aterm); -static void pr_ptset_aterm_elem (aterm); -static void pta_pr_ptset (contents_type); - -/* Hook for debugging. This function is called instead of - aterm_inclusion, and lets us print the actual constraints as they - are generated. */ - -static void -term_inclusion (aterm t1, aterm t2) -{ - if (dump_file) - { - fprintf (dump_file, "Constraint: "); - aterm_print (dump_file, t1); - fprintf (dump_file, " <= "); - aterm_print (dump_file, t2); - fprintf (dump_file, "\n"); - } - - aterm_inclusion (t1, t2); -} - -/* Initialize libbanshee's constraint engine. */ - -static void -pta_init (void) -{ - andersen_terms_init (); -} - -/* Reset libbanshee's constraint engine. We do this when we are done - using it, as it releases the memory libbanshee is using. */ - -static void -pta_reset (void) -{ - andersen_terms_reset (); -} - -static aterm -get_ref (aterm t) -{ - struct ref_decon r_decon; - r_decon = ref_decon (t); - - assert (r_decon.f1); - - return r_decon.f1; -} - -/* Make a function record out of the arguments. */ - -static argterm -fun_rec_aterm (aterm_list args) -{ - region scratch; - int counter = 0; - argterm rest, result; - aterm_list_scanner scan; - aterm temp; - char field_name[512]; - argterm_map map; - - scratch = newregion (); - map = new_argterm_map (scratch); - aterm_list_scan (args, &scan); - while (aterm_list_next (&scan, &temp)) - { - snprintf (field_name, 512, "%d", counter++); - argterm_map_cons (argterm_make_field (field_name, temp), map); - } - - rest = argterm_wild (); - /* rest = argterm_fresh(); */ - - /* safe since field_add makes a copy of the string*/ - result = argterm_row (map, rest); - - deleteregion (scratch); - - return result; -} - - -static aterm -pta_make_lam (const char *id, aterm ret, aterm_list args) -{ - return lam (label_term_constant (id), fun_rec_aterm (args), ret); -} - -/* Make a label reference to the given id. */ - -static aterm -pta_make_ref (const char *id) -{ - - aterm var = aterm_fresh (id); - - label_term tag = label_term_constant (id); - - return ref (tag, var, var); -} - -/* Return the empty set. */ - -static aterm -pta_bottom (void) -{ - return aterm_zero (); -} - -/* Join two terms, such that anything in set t1 will also be in set - t2, and vice versa. */ - -static aterm -pta_join (aterm t1, aterm t2) -{ - aterm result; - region scratch_rgn = newregion (); - aterm_list list = new_aterm_list (scratch_rgn); - - aterm_list_cons (t1, list); - aterm_list_cons (t2, list); - - - result = aterm_union (list); - deleteregion (scratch_rgn); - - return result; -} - -/* Generate the constraint for a dereference of term t1. */ - -static aterm -pta_deref (aterm t1) -{ - return ref_proj2 (t1); -} - -/* Generate the constraint for t1 being an rvalue. */ - -static aterm -pta_rvalue (aterm t1) -{ - return pta_deref (t1); -} - -/* Generate the constraint for taking the address of t1. */ - -static aterm -pta_address (aterm t1) -{ - return ref (label_term_one (), aterm_one (), t1); -} - -/* Generate the constraint for assigning t2 to t1. */ - -static void -pta_assignment (aterm t1, aterm t2) -{ - term_inclusion (t1, ref_pat1 (t2)); -} - -/* Make a function from the given name, return value, and arguments. */ - -static aterm -pta_make_fun (const char *name, aterm ret, aterm_list args) -{ - aterm temp; - aterm_list_scanner scan; - region scratch_rgn = newregion (); - aterm_list arg_list = new_aterm_list (scratch_rgn); - - aterm_list_scan (args, &scan); - - while (aterm_list_next (&scan, &temp)) - { - aterm_list_cons (get_ref (temp), arg_list); - } - - return pta_make_lam (name, get_ref (ret), arg_list); -} - -/* Return the constraint for calling function T with arguments - ACTUALS. */ - -static aterm -pta_application (aterm t, aterm_list actuals) -{ - argterm args = fun_rec_aterm (actuals); - - term_inclusion (t, lam_pat1 (args)); - return pta_address (lam_proj2 (t)); -} - -/* Return the contents of set expression T. */ - -static contents_type -pta_get_contents (aterm t) -{ - struct ref_decon t_decon; - t_decon = ref_decon (t); - - return t_decon.f1; -} - -/* Print out a points-to set element. */ - -static void -pr_ptset_aterm_elem (aterm t) -{ - struct ref_decon ref; - struct lam_decon lam; - - ref = ref_decon (t); - lam = lam_decon (t); - - fprintf (dump_file, ","); - if (ref.f0) - label_term_print (dump_file, ref.f0); - else if (lam.f0) - label_term_print (dump_file, lam.f0); -} - - -/* Print out a points-to set. */ - -static void -pta_pr_ptset (contents_type t) -{ - int size; - region scratch_rgn; - aterm_list ptset; - scratch_rgn = newregion (); - ptset = aterm_list_copy (scratch_rgn, aterm_tlb (t)); - - size = aterm_list_length (ptset); - - fprintf (dump_file, "{"); - if (!aterm_list_empty (ptset)) - { - struct ref_decon ref; - struct lam_decon lam; - ref = ref_decon (aterm_list_head (ptset)); - lam = lam_decon (aterm_list_head (ptset)); - if (ref.f0) - label_term_print (dump_file, ref.f0); - else if (lam.f0) - label_term_print (dump_file, lam.f0); - - /* aterm_pr(stdout,aterm_hd(ptset)); */ - ptset = aterm_list_tail (ptset); - } - aterm_list_app (ptset, pr_ptset_aterm_elem); - fprintf (dump_file, "}(%d)\n", size); - deleteregion (scratch_rgn); -} - -/* Initialize Andersen alias analysis. */ -static int initted = 0; - -static void -andersen_init (struct tree_alias_ops *ops ATTRIBUTE_UNUSED) -{ -#if 0 - /* Don't claim we can do ip partial unless we have unit_at_a_time on. */ - if (!flag_unit_at_a_time) -#endif - andersen_ops.ip_partial = 0; - if (!initted || (!andersen_ops.ip_partial && !andersen_ops.ip)) - { - pta_init (); - andersen_rgn = newregion (); - initted = 1; - } - - ptamap = splay_tree_new (splay_tree_compare_pointers, NULL, NULL); - -} - -static int -print_out_result (splay_tree_node node, void *data ATTRIBUTE_UNUSED) -{ - fprintf (dump_file, "%s :=", - alias_get_name (ALIAS_VAR_DECL (((alias_var) node->value)))); - pta_pr_ptset (pta_get_contents ((aterm) node->key)); - return 0; -} - -/* Cleanup after Andersen alias analysis. */ - -static void -andersen_cleanup (struct tree_alias_ops *ops ATTRIBUTE_UNUSED) -{ - if (dump_file) - { - if (dump_flags & TDF_STATS) - { - fprintf (dump_file, "\nPoints-to stats:\n"); - andersen_terms_stats (dump_file); - } - - fprintf (dump_file, "\nPoints-to sets:\n"); - splay_tree_foreach (ptamap, print_out_result, NULL); - } - - splay_tree_delete (ptamap); - - if (!andersen_ops.ip_partial && !andersen_ops.ip) - { - pta_reset (); - deleteregion (andersen_rgn); - andersen_rgn = NULL; - } -} - -/* Add decl to the analyzer, and return a var for it. For - Andersen, we create a new alias var for the declaration, and - return that. */ - -static alias_var -andersen_add_var (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, tree decl) -{ - alias_var ret; - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Adding variable %s\n", - alias_get_name (decl)); - - if (alias_get_name (decl) != NULL) - { - ret = alias_var_new_with_aterm (decl, - pta_make_ref (alias_get_name (decl))); - } - else - { - char *tmp_name; - ASM_FORMAT_PRIVATE_NAME (tmp_name, "unnamed var", id_num++); - ret = alias_var_new_with_aterm (decl, pta_make_ref (tmp_name)); - } - splay_tree_insert (ptamap, (splay_tree_key) ALIAS_VAR_ATERM (ret), - (splay_tree_value) ret); - ALIAS_VAR_PTSET (ret) = NULL; - - return ret; -} - -/* Add a variable to the analyzer that is equivalent (as far as - aliases go) to some existing alias variable. - For Andersen, we just call a function that does this for us. */ - -static alias_var -andersen_add_var_same (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, tree decl, - alias_var tv) -{ - alias_var ret; - - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Adding variable %s same as %s\n", - alias_get_name (decl), alias_get_name (ALIAS_VAR_DECL (tv))); - - if (alias_get_name (decl) != NULL) - ret = alias_var_new_with_aterm (decl, - pta_make_ref (alias_get_name (decl))); - else - { - char *tmp_name; - ASM_FORMAT_PRIVATE_NAME (tmp_name, "unnamed var", id_num++); - ret = alias_var_new_with_aterm (decl, pta_make_ref (tmp_name)); - } - - pta_join (ALIAS_VAR_ATERM (tv), ALIAS_VAR_ATERM (ret)); - splay_tree_insert (ptamap, (splay_tree_key) ALIAS_VAR_ATERM (ret), - (splay_tree_value) ret); - ALIAS_VAR_PTSET (tv) = NULL; - ALIAS_VAR_PTSET (ret) = NULL; - - return ret; -} - -/* Inference for simple assignment (lhs = rhs) */ - -static void -andersen_simple_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var lhs, alias_var rhs) -{ - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Simple assignment %s = %s\n", - alias_get_name (ALIAS_VAR_DECL (lhs)), - alias_get_name (ALIAS_VAR_DECL (rhs))); - if (lhs == rhs) - return; - - /* The rvalue is just the term itself, and we generate a constraint - for assigning it to the lhs. */ - pta_assignment (ALIAS_VAR_ATERM (lhs), - pta_rvalue (ALIAS_VAR_ATERM (rhs))); -} - -/* Inference for address assignment (lhs = &addr) */ - -static void -andersen_addr_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var lhs, alias_var addr) -{ - if (addr == NULL) - return; - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Address assignment %s = &%s\n", - alias_get_name (ALIAS_VAR_DECL (lhs)), - alias_get_name (ALIAS_VAR_DECL (addr))); - - /* The rvalue here is the address of a term, and we generate a - constraint to assign this address to the lhs. */ - pta_assignment (ALIAS_VAR_ATERM (lhs), - pta_rvalue (pta_address (ALIAS_VAR_ATERM (addr)))); -} - - -/* Inference for pointer assignment (lhs = *ptr) */ - -static void -andersen_ptr_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var lhs, alias_var ptr) -{ - - if (ptr == NULL) - return; - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Pointer assignment %s = *%s\n", - alias_get_name (ALIAS_VAR_DECL (lhs)), - alias_get_name (ALIAS_VAR_DECL (ptr))); - - pta_assignment (ALIAS_VAR_ATERM (lhs), - pta_rvalue (pta_deref (ALIAS_VAR_ATERM (ptr)))); - -} - -/* Determine if OP destroys the current assumed to be valid pointer - (whether it generates a new valid pointer is not relevant). */ - -static bool -pointer_destroying_op (tree op) -{ - switch (TREE_CODE (op)) - { - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_NOT_EXPR: - case LT_EXPR: - case GT_EXPR: - case GE_EXPR: - case LE_EXPR: - case EQ_EXPR: - case NE_EXPR: - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - case LROTATE_EXPR: - case RROTATE_EXPR: - return true; - default: - return false; - } - return false; -} - -/* Inference rule for operations (lhs = operation(operands)). */ - -static void -andersen_op_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var lhs, varray_type operands, tree operation, - bitmap addrargs) -{ - aterm newvar = NULL; - - if (VARRAY_ACTIVE_SIZE (operands) == 0) - return; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Op assignment %s = ", - alias_get_name (ALIAS_VAR_DECL (lhs))); - print_generic_stmt (dump_file, operation, dump_flags); - fprintf (dump_file, "\n"); - } - - - /* Pointer destroying operations do not give us the same valid pointer - back, and thus, are assignment to pta_bottom. */ - if (pointer_destroying_op (operation)) - { - pta_assignment (ALIAS_VAR_ATERM (lhs), pta_rvalue (pta_bottom ())); - return; - } - - /* Operations in general we can't track the exact effect of. Thus, - we conservatively assume that it could make the LHS point to - *anything* the RHS points to. To signify this, we join the RHS - variables together and assign it to the LHS. */ - /* The >2 case occurs when we are dealing with constructors. */ - if (VARRAY_ACTIVE_SIZE (operands) > 2) - { - size_t i; - alias_var tv1 = VARRAY_GENERIC_PTR (operands, 0); - newvar = ALIAS_VAR_ATERM (tv1); - for (i = 1; i < VARRAY_ACTIVE_SIZE (operands); i++) - { - alias_var tempvar = VARRAY_GENERIC_PTR (operands, i); - aterm t2 = ALIAS_VAR_ATERM (tempvar); - if (bitmap_bit_p (addrargs, i)) - newvar = pta_join (newvar, pta_address (t2)); - else - newvar = pta_join (newvar, t2); - } - } - else if (VARRAY_ACTIVE_SIZE (operands) == 2) - { - alias_var tv1 = VARRAY_GENERIC_PTR (operands, 0); - alias_var tv2 = VARRAY_GENERIC_PTR (operands, 1); - aterm t1 = ALIAS_VAR_ATERM (tv1); - aterm t2 = ALIAS_VAR_ATERM (tv2); - if (bitmap_bit_p (addrargs, 0) && bitmap_bit_p (addrargs, 1)) - newvar = pta_join (pta_address (t1), pta_address (t2)); - else if (bitmap_bit_p (addrargs, 0)) - newvar = pta_join (pta_address (t1), t2); - else if (bitmap_bit_p (addrargs, 1)) - newvar = pta_join (t1, pta_address (t2)); - else - newvar = pta_join (t1, t2); - } - else if (VARRAY_ACTIVE_SIZE (operands) == 1) - { - alias_var tv1 = VARRAY_GENERIC_PTR (operands, 0); - aterm t1 = ALIAS_VAR_ATERM (tv1); - if (bitmap_bit_p (addrargs, 0)) - newvar = pta_address (t1); - else - newvar = t1; - } - pta_assignment (ALIAS_VAR_ATERM (lhs), pta_rvalue (newvar)); -} - -/* Inference for heap assignment (lhs = alloc). */ - -static void -andersen_heap_assign (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var lhs ATTRIBUTE_UNUSED) -{ -#if 0 - alias_type type1; - ECR tau; - type1 = ECR_get_type (alias_var_get_ECR (lhs)); - tau = alias_ltype_loc (type1); - - if (ECR_get_type (tau) == alias_bottom) - ECR_set_type (tau, alias_ltype_new ()); -#endif -} - -/* Inference for assignment to a pointer (*ptr = rhs). */ - -static void -andersen_assign_ptr (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var ptr, alias_var rhs) -{ - - if (rhs == NULL) - return; - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Assignment to pointer *%s = %s\n", - alias_get_name (ALIAS_VAR_DECL (ptr)), - alias_get_name (ALIAS_VAR_DECL (rhs))); - /* The RHS is a standard rvalue, and the LHS is a pointer - dereference. */ - pta_assignment (pta_deref (ALIAS_VAR_ATERM (ptr)), - pta_rvalue (ALIAS_VAR_ATERM (rhs))); -} - -/* Inference for a function definition. */ - -static void -andersen_function_def (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var func, varray_type params, - alias_var retval) -{ - aterm_list args = new_aterm_list (andersen_rgn); - aterm fun_type; - - size_t l = VARRAY_ACTIVE_SIZE (params); - size_t i; - - /* Set up the arguments for the new function type. */ - for (i = 0; i < l; i++) - { - alias_var tv = VARRAY_GENERIC_PTR (params, i); - aterm_list_cons (ALIAS_VAR_ATERM (tv), args); - } - /* Create the function type. */ - fun_type = pta_make_fun (alias_get_name (ALIAS_VAR_DECL (func)), - ALIAS_VAR_ATERM (retval), args); - - /* Assign the function type itself to the function. */ - pta_assignment (ALIAS_VAR_ATERM (func), fun_type); -} - -/* Inference for a function call assignment. */ - -static int -andersen_function_call (struct tree_alias_ops *ops, - alias_var lhs, alias_var func, - varray_type args, bitmap addrargs) -{ - aterm_list actuals = new_aterm_list (andersen_rgn); - aterm ftype = ALIAS_VAR_ATERM (func); - aterm ret = NULL; - aterm res; - tree decl = ALIAS_VAR_DECL (func); - - size_t i; - - if (lhs) - ret = ALIAS_VAR_ATERM (lhs); - for (i = 0; i < VARRAY_ACTIVE_SIZE (args); i++) - { - alias_var argtv = VARRAY_GENERIC_PTR (args, i); - aterm arg = ALIAS_VAR_ATERM (argtv); - if (bitmap_bit_p (addrargs, i)) - aterm_list_cons (pta_rvalue (pta_address (arg)), actuals); - else - aterm_list_cons (pta_rvalue (arg), actuals); - } - aterm_list_reverse (actuals); - - /* Generate the constraint that calls the function with it's - arguments, and gives us the result. This in turn applies - whatever constraints are in that function. */ - res = pta_application (pta_rvalue (ftype), actuals); - /* We only need care about the result if we have an LHS. If we do, - assign the result of function application back to the LHS. */ - if (ret) - pta_assignment (ret, pta_rvalue (res)); - - /* We can handle functions we've got trees for. non-statics will - just have incoming parameters assigned to global_var if - necessary. */ - if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_PTA_ALIASVAR (decl) - && ops->ip_partial - && (cgraph_local_info (decl)->local)) - { - return 0; - } - return 1; -} - - -/* Simple pointer comparison function for list sorting. */ - -static int -simple_cmp (const aterm a, const aterm b) -{ - return (int *)a - (int *)b; -} - - -/* Get the points-to set for TV, caching if it we had to compute it. */ - -static aterm_list -get_ptset (alias_var tv) -{ - aterm_list ptset; - ptset = ALIAS_VAR_PTSET (tv); - if (ptset != NULL) - return ptset; - ptset = aterm_tlb (pta_get_contents (ALIAS_VAR_ATERM (tv))); - ALIAS_VAR_PTSET (tv) = ptset; - return ptset; -} - - -/* Determine if two aterm's have the same points-to set. */ - -static bool -andersen_same_points_to_set (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var ptrtv, alias_var vartv) -{ - aterm_list ptset1, ptset2; - aterm_list_scanner scan1, scan2; - aterm data1, data2; - region scratch_rgn = newregion (); - - ptset1 = get_ptset (ptrtv); - ptset2 = get_ptset (vartv); - - if (aterm_list_length (ptset1) != aterm_list_length (ptset2)) - { - deleteregion (scratch_rgn); - return false; - } - - if (ptset1 == ptset2) - { - deleteregion (scratch_rgn); - return true; - } - - ptset1 = aterm_list_copy (scratch_rgn, ptset1); - ptset2 = aterm_list_copy (scratch_rgn, ptset2); - - if (aterm_list_length (ptset1) != aterm_list_length (ptset2)) - { - deleteregion (scratch_rgn); - return false; - } - - ptset1 = aterm_list_sort (ptset1, simple_cmp); - ptset2 = aterm_list_sort (ptset2, simple_cmp); - - aterm_list_scan (ptset1, &scan1); - aterm_list_scan (ptset2, &scan2); - while (aterm_list_next (&scan1, &data1)) - { - aterm_list_next (&scan2, &data2); - if (data1 != data2) - { - deleteregion(scratch_rgn); - return false; - } - } - deleteregion(scratch_rgn); - return true; -} - - -/* Determine if two variables may alias. In our case, this means - whether the decl represented by PTRTV can point to VARTV. */ - -static bool -andersen_may_alias (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var ptrtv, alias_var vartv) -{ - aterm_list ptset; - ptset = get_ptset (ptrtv); - - if (aterm_list_empty (ptset)) - return false; - - return aterm_list_member (ptset, ALIAS_VAR_ATERM (vartv)); -} - -/* Determine whether PTRTV has an empty points-to set. IE it may not - point to anything. */ - -static bool -andersen_empty_points_to_set (struct tree_alias_ops *ops ATTRIBUTE_UNUSED, - alias_var ptrtv) -{ - aterm_list ptset; - ptset = get_ptset (ptrtv); - return aterm_list_empty (ptset); -} |