OSDN Git Service

* tree-ssa-structalias.c: Don't include expr.h.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-structalias.c
index 5ca2a5c..f48bcb2 100644 (file)
@@ -16,7 +16,7 @@ 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
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
 #include "config.h"
@@ -34,7 +34,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #include "basic-block.h"
 #include "output.h"
 #include "errors.h"
-#include "expr.h"
 #include "diagnostic.h"
 #include "tree.h"
 #include "c-common.h"
@@ -988,8 +987,8 @@ build_constraint_graph (void)
 static unsigned int changed_count;
 static sbitmap changed;
 
-DEF_VEC_I(uint);
-DEF_VEC_ALLOC_I(uint,heap);
+DEF_VEC_I(unsigned);
+DEF_VEC_ALLOC_I(unsigned,heap);
 
 
 /* Strongly Connected Component visitation info.  */
@@ -1000,8 +999,8 @@ struct scc_info
   sbitmap in_component;
   int current_index;
   unsigned int *visited_index;
-  VEC(uint,heap) *scc_stack;
-  VEC(uint,heap) *unification_queue;
+  VEC(unsigned,heap) *scc_stack;
+  VEC(unsigned,heap) *unification_queue;
 };
 
 
@@ -1051,18 +1050,18 @@ scc_visit (constraint_graph_t graph, struct scc_info *si, unsigned int n)
     {
       unsigned int t = si->visited_index[n];
       SET_BIT (si->in_component, n);
-      while (VEC_length (uint, si->scc_stack) != 0 
-            && t < si->visited_index[VEC_last (uint, si->scc_stack)])
+      while (VEC_length (unsigned, si->scc_stack) != 0 
+            && t < si->visited_index[VEC_last (unsigned, si->scc_stack)])
        {
-         unsigned int w = VEC_pop (uint, si->scc_stack);
+         unsigned int w = VEC_pop (unsigned, si->scc_stack);
          get_varinfo (w)->node = n;
          SET_BIT (si->in_component, w);
          /* Mark this node for collapsing.  */
-         VEC_safe_push (uint, heap, si->unification_queue, w);
+         VEC_safe_push (unsigned, heap, si->unification_queue, w);
        } 
     }
   else
-    VEC_safe_push (uint, heap, si->scc_stack, n);
+    VEC_safe_push (unsigned, heap, si->scc_stack, n);
 }
 
 
@@ -1132,9 +1131,9 @@ process_unification_queue (constraint_graph_t graph, struct scc_info *si,
        changed rep's solution.
        
        Delete any 0 weighted self-edges we now have for rep.  */
-  while (i != VEC_length (uint, si->unification_queue))
+  while (i != VEC_length (unsigned, si->unification_queue))
     {
-      unsigned int tounify = VEC_index (uint, si->unification_queue, i);
+      unsigned int tounify = VEC_index (unsigned, si->unification_queue, i);
       unsigned int n = get_varinfo (tounify)->node;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1167,8 +1166,8 @@ process_unification_queue (constraint_graph_t graph, struct scc_info *si,
       /* If we've either finished processing the entire queue, or
         finished processing all nodes for component n, update the solution for
         n.  */
-      if (i == VEC_length (uint, si->unification_queue)
-         || get_varinfo (VEC_index (uint, si->unification_queue, i))->node != n)
+      if (i == VEC_length (unsigned, si->unification_queue)
+         || get_varinfo (VEC_index (unsigned, si->unification_queue, i))->node != n)
        {
          struct constraint_edge edge;
 
@@ -1206,7 +1205,7 @@ struct topo_info
   sbitmap visited;
   /* Array that stores the topological order of the graph, *in
      reverse*.  */
-  VEC(uint,heap) *topo_order;
+  VEC(unsigned,heap) *topo_order;
 };
 
 
@@ -1219,7 +1218,7 @@ init_topo_info (void)
   struct topo_info *ti = xmalloc (sizeof (struct topo_info));
   ti->visited = sbitmap_alloc (size);
   sbitmap_zero (ti->visited);
-  ti->topo_order = VEC_alloc (uint, heap, 1);
+  ti->topo_order = VEC_alloc (unsigned, heap, 1);
   return ti;
 }
 
@@ -1230,7 +1229,7 @@ static void
 free_topo_info (struct topo_info *ti)
 {
   sbitmap_free (ti->visited);
-  VEC_free (uint, heap, ti->topo_order);
+  VEC_free (unsigned, heap, ti->topo_order);
   free (ti);
 }
 
@@ -1250,7 +1249,7 @@ topo_visit (constraint_graph_t graph, struct topo_info *ti,
       if (!TEST_BIT (ti->visited, c->dest))
        topo_visit (graph, ti, c->dest);
     }
-  VEC_safe_push (uint, heap, ti->topo_order, n);
+  VEC_safe_push (unsigned, heap, ti->topo_order, n);
 }
 
 /* Return true if variable N + OFFSET is a legal field of N.  */
@@ -1447,8 +1446,8 @@ init_scc_info (void)
   si->in_component = sbitmap_alloc (size);
   sbitmap_ones (si->in_component);
   si->visited_index = xcalloc (sizeof (unsigned int), size + 1);
-  si->scc_stack = VEC_alloc (uint, heap, 1);
-  si->unification_queue = VEC_alloc (uint, heap, 1);
+  si->scc_stack = VEC_alloc (unsigned, heap, 1);
+  si->unification_queue = VEC_alloc (unsigned, heap, 1);
   return si;
 }
 
@@ -1460,8 +1459,8 @@ free_scc_info (struct scc_info *si)
   sbitmap_free (si->visited);
   sbitmap_free (si->in_component);
   free (si->visited_index);
-  VEC_free (uint, heap, si->scc_stack);
-  VEC_free (uint, heap, si->unification_queue);
+  VEC_free (unsigned, heap, si->scc_stack);
+  VEC_free (unsigned, heap, si->unification_queue);
   free(si); 
 }
 
@@ -1534,9 +1533,9 @@ perform_var_substitution (constraint_graph_t graph)
      node in topological order.  */
   compute_topo_order (graph, ti);
  
-  while (VEC_length (uint, ti->topo_order) != 0)
+  while (VEC_length (unsigned, ti->topo_order) != 0)
     {
-      unsigned int i = VEC_pop (uint, ti->topo_order);
+      unsigned int i = VEC_pop (unsigned, ti->topo_order);
       unsigned int pred;
       varinfo_t vi = get_varinfo (i);
       bool okay_to_elim = false;
@@ -1660,9 +1659,9 @@ solve_graph (constraint_graph_t graph)
 
       compute_topo_order (graph, ti);
 
-      while (VEC_length (uint, ti->topo_order) != 0)
+      while (VEC_length (unsigned, ti->topo_order) != 0)
        {
-         i = VEC_pop (uint, ti->topo_order);
+         i = VEC_pop (unsigned, ti->topo_order);
          gcc_assert (get_varinfo (i)->node == i);
 
          /* If the node has changed, we need to process the
@@ -1940,6 +1939,25 @@ bitpos_of_field (const tree fdecl)
 }
 
 
+/* Return true if an access to [ACCESSPOS, ACCESSSIZE]
+   overlaps with a field at [FIELDPOS, FIELDSIZE] */
+
+static bool
+offset_overlaps_with_access (const unsigned HOST_WIDE_INT fieldpos,
+                            const unsigned HOST_WIDE_INT fieldsize,
+                            const unsigned HOST_WIDE_INT accesspos,
+                            const unsigned HOST_WIDE_INT accesssize)
+{
+  if (fieldpos == accesspos && fieldsize == accesssize)
+    return true;
+  if (accesspos >= fieldpos && accesspos < (fieldpos + fieldsize))
+    return true;
+  if (accesspos < fieldpos && (accesspos + accesssize > fieldpos))
+    return true;
+  
+  return false;
+}
+
 /* Given a COMPONENT_REF T, return the constraint_expr for it.  */
 
 static struct constraint_expr
@@ -2000,8 +2018,27 @@ get_constraint_for_component_ref (tree t)
         we may have to do something cute here.  */
       
       if (result.offset < get_varinfo (result.var)->fullsize)  
-       result.var = first_vi_for_offset (get_varinfo (result.var), 
-                                         result.offset)->id;
+       {
+         /* It's also not true that the constraint will actually start at the
+            right offset, it may start in some padding.  We only care about
+            setting the constraint to the first actual field it touches, so
+            walk to find it.  */ 
+         varinfo_t curr;
+         for (curr = get_varinfo (result.var); curr; curr = curr->next)
+           {
+             if (offset_overlaps_with_access (curr->offset, curr->size,
+                                              result.offset, bitsize))
+               {
+                 result.var = curr->id;
+                 break;
+
+               }
+           }
+         /* assert that we found *some* field there. The user couldn't be
+            accessing *only* padding.  */
+            
+         gcc_assert (curr);
+       }
       else
        if (dump_file && (dump_flags & TDF_DETAILS))
          fprintf (dump_file, "Access to past the end of variable, ignoring\n");
@@ -2210,8 +2247,7 @@ do_simple_structure_copy (const struct constraint_expr lhs,
                          const unsigned HOST_WIDE_INT size)
 {
   varinfo_t p = get_varinfo (lhs.var);
-  unsigned HOST_WIDE_INT pstart,last;
-
+  unsigned HOST_WIDE_INT pstart, last;
   pstart = p->offset;
   last = p->offset + size;
   for (; p && p->offset < last; p = p->next)
@@ -2321,8 +2357,6 @@ do_structure_copy (tree lhsop, tree rhsop)
   unsigned HOST_WIDE_INT lhssize;
   unsigned HOST_WIDE_INT rhssize;
 
-  lhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (lhsop)));
-  rhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (rhsop)));
   lhs = get_constraint_for (lhsop);  
   rhs = get_constraint_for (rhsop);
   
@@ -2334,8 +2368,18 @@ do_structure_copy (tree lhsop, tree rhsop)
       rhs = tmp;
     }
   
-  /* If the RHS is a special var, set all the LHS fields to that
-     special var.  */
+  /*  This is fairly conservative for the RHS == ADDRESSOF case, in that it's
+      possible it's something we could handle.  However, most cases falling
+      into this are dealing with transparent unions, which are slightly
+      weird. */
+  if (rhs.type == ADDRESSOF && rhs.var > integer_id)
+    {
+      rhs.type = ADDRESSOF;
+      rhs.var = anything_id;
+    }
+
+  /* If the RHS is a special var, or an addressof, set all the LHS fields to
+     that special var.  */
   if (rhs.var <= integer_id)
     {
       for (p = get_varinfo (lhs.var); p; p = p->next)
@@ -2351,6 +2395,20 @@ do_structure_copy (tree lhsop, tree rhsop)
     }
   else
     {
+      /* The size only really matters insofar as we don't set more or less of
+        the variable.  If we hit an unknown size var, the size should be the
+        whole darn thing.  */
+      if (get_varinfo (rhs.var)->is_unknown_size_var)
+       rhssize = ~0;
+      else
+       rhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (rhsop)));
+
+      if (get_varinfo (lhs.var)->is_unknown_size_var)
+       lhssize = ~0;
+      else
+       lhssize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (lhsop)));
+
+  
       if (rhs.type == SCALAR && lhs.type == SCALAR)  
        do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
       else if (lhs.type != DEREF && rhs.type == DEREF)
@@ -2362,14 +2420,12 @@ do_structure_copy (tree lhsop, tree rhsop)
          tree rhsdecl = get_varinfo (rhs.var)->decl;
          tree pointertype = TREE_TYPE (rhsdecl);
          tree pointedtotype = TREE_TYPE (pointertype);
-         tree tmpvar;
+         tree tmpvar;  
+
          gcc_assert (rhs.type == DEREF && lhs.type == DEREF);
          tmpvar = create_tmp_var_raw (pointedtotype, "structcopydereftmp");
-         lhs = get_constraint_for (tmpvar);
-         do_rhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
-         rhs = lhs;
-         lhs = get_constraint_for (lhsop);
-         do_lhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
+         do_structure_copy (tmpvar, rhsop);
+         do_structure_copy (lhsop, tmpvar);
        }
     }
 }
@@ -2723,7 +2779,7 @@ create_variable_info_for (tree decl, const char *name)
   vi->offset = 0;
   vi->has_union = hasunion;
   if (!TYPE_SIZE (decltype) 
-      || TREE_CODE (TYPE_SIZE  (decltype)) != INTEGER_CST
+      || TREE_CODE (TYPE_SIZE (decltype)) != INTEGER_CST
       || TREE_CODE (decltype) == ARRAY_TYPE
       || TREE_CODE (decltype) == UNION_TYPE
       || TREE_CODE (decltype) == QUAL_UNION_TYPE)
@@ -2786,7 +2842,6 @@ create_variable_info_for (tree decl, const char *name)
        }
       
       field = fo->field;
-      gcc_assert (bitpos_of_field (field) == 0);
       vi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
       for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
        {
@@ -2895,13 +2950,13 @@ set_uids_in_ptset (bitmap into, bitmap from)
          subvar_t svars = get_subvars_for_var (vi->decl);
          subvar_t sv;
          for (sv = svars; sv; sv = sv->next)
-           bitmap_set_bit (into, var_ann (sv->var)->uid);    
+           bitmap_set_bit (into, DECL_UID (sv->var));
        }
       /* We may end up with labels in the points-to set because people
         take their address, and they are _DECL's.  */
       else if (TREE_CODE (vi->decl) == VAR_DECL 
          || TREE_CODE (vi->decl) == PARM_DECL)
-       bitmap_set_bit (into, var_ann (vi->decl)->uid);
+       bitmap_set_bit (into, DECL_UID (vi->decl));
 
          
     }
@@ -3049,8 +3104,10 @@ init_base_vars (void)
   rhs.var = anything_id;
   rhs.offset = 0;
   var_anything->address_taken = true;
-  process_constraint (new_constraint (lhs, rhs));
-
+  /* This specifically does not use process_constraint because
+     process_constraint ignores all anything = anything constraints, since all
+     but this one are redundant.  */
+  VEC_safe_push (constraint_t, gc, constraints, new_constraint (lhs, rhs));
   
   /* Create the READONLY variable, used to represent that a variable
      points to readonly memory.  */
@@ -3075,7 +3132,6 @@ init_base_vars (void)
   rhs.type = ADDRESSOF;
   rhs.var = anything_id;
   rhs.offset = 0;
-  var_readonly->address_taken = true;
   
   process_constraint (new_constraint (lhs, rhs));
   
@@ -3091,6 +3147,16 @@ init_base_vars (void)
   var_integer->next = NULL;
   integer_id = 3;
   VEC_safe_push (varinfo_t, gc, varmap, var_integer);
+
+  /* *INTEGER = ANYTHING, because we don't know where a dereference of a random
+     integer will point to.  */
+  lhs.type = SCALAR;
+  lhs.var = integer_id;
+  lhs.offset = 0;
+  rhs.type = ADDRESSOF;
+  rhs.var = anything_id;
+  rhs.offset = 0;
+  process_constraint (new_constraint (lhs, rhs));
 }  
 
 
@@ -3101,7 +3167,6 @@ static void
 create_alias_vars (void)
 {
   basic_block bb;
-
   
   init_alias_vars ();