diff gcc/tree-object-size.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents a06113de4d67
children b7f97abdc517
line wrap: on
line diff
--- a/gcc/tree-object-size.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/gcc/tree-object-size.c	Fri Feb 12 23:39:51 2010 +0900
@@ -1,5 +1,6 @@
 /* __builtin_object_size (ptr, object_size_type) computation
-   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by Jakub Jelinek <jakub@redhat.com>
 
 This file is part of GCC.
@@ -42,7 +43,8 @@
 static unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
 
 static tree compute_object_offset (const_tree, const_tree);
-static unsigned HOST_WIDE_INT addr_object_size (const_tree, int);
+static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *,
+						const_tree, int);
 static unsigned HOST_WIDE_INT alloc_object_size (const_gimple, int);
 static tree pass_through_call (const_gimple);
 static void collect_object_sizes_for (struct object_size_info *, tree);
@@ -151,9 +153,10 @@
    If unknown, return unknown[object_size_type].  */
 
 static unsigned HOST_WIDE_INT
-addr_object_size (const_tree ptr, int object_size_type)
+addr_object_size (struct object_size_info *osi, const_tree ptr,
+		  int object_size_type)
 {
-  tree pt_var;
+  tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
 
   gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
 
@@ -162,58 +165,190 @@
     pt_var = get_base_address (pt_var);
 
   if (pt_var
-      && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST)
-      && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
-      && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
-      && (unsigned HOST_WIDE_INT)
-	 tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) < offset_limit)
+      && TREE_CODE (pt_var) == INDIRECT_REF
+      && TREE_CODE (TREE_OPERAND (pt_var, 0)) == SSA_NAME
+      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var, 0))))
     {
-      tree bytes;
+      unsigned HOST_WIDE_INT sz;
+
+      if (!osi || (object_size_type & 1) != 0)
+	sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
+					  object_size_type & ~1);
+      else
+	{
+	  tree var = TREE_OPERAND (pt_var, 0);
+	  if (osi->pass == 0)
+	    collect_object_sizes_for (osi, var);
+	  if (bitmap_bit_p (computed[object_size_type],
+			    SSA_NAME_VERSION (var)))
+	    sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
+	  else
+	    sz = unknown[object_size_type];
+	}
 
-      if (pt_var != TREE_OPERAND (ptr, 0))
-	{
-	  tree var;
+      if (sz != unknown[object_size_type] && sz < offset_limit)
+	pt_var_size = size_int (sz);
+    }
+  else if (pt_var
+	   && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST)
+	   && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
+	   && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
+	   && (unsigned HOST_WIDE_INT)
+	      tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
+	      < offset_limit)
+    pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
+  else
+    return unknown[object_size_type];
 
-	  if (object_size_type & 1)
-	    {
-	      var = TREE_OPERAND (ptr, 0);
+  if (pt_var != TREE_OPERAND (ptr, 0))
+    {
+      tree var;
+
+      if (object_size_type & 1)
+	{
+	  var = TREE_OPERAND (ptr, 0);
 
-	      while (var != pt_var
-		      && TREE_CODE (var) != BIT_FIELD_REF
-		      && TREE_CODE (var) != COMPONENT_REF
-		      && TREE_CODE (var) != ARRAY_REF
-		      && TREE_CODE (var) != ARRAY_RANGE_REF
-		      && TREE_CODE (var) != REALPART_EXPR
-		      && TREE_CODE (var) != IMAGPART_EXPR)
-		var = TREE_OPERAND (var, 0);
-	      if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
-		var = TREE_OPERAND (var, 0);
-	      if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
-		  || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
-		  || tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)),
-				      TYPE_SIZE_UNIT (TREE_TYPE (var))))
+	  while (var != pt_var
+		 && TREE_CODE (var) != BIT_FIELD_REF
+		 && TREE_CODE (var) != COMPONENT_REF
+		 && TREE_CODE (var) != ARRAY_REF
+		 && TREE_CODE (var) != ARRAY_RANGE_REF
+		 && TREE_CODE (var) != REALPART_EXPR
+		 && TREE_CODE (var) != IMAGPART_EXPR)
+	    var = TREE_OPERAND (var, 0);
+	  if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
+	    var = TREE_OPERAND (var, 0);
+	  if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
+	      || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
+	      || (pt_var_size
+		  && tree_int_cst_lt (pt_var_size,
+				      TYPE_SIZE_UNIT (TREE_TYPE (var)))))
+	    var = pt_var;
+	  else if (var != pt_var && TREE_CODE (pt_var) == INDIRECT_REF)
+	    {
+	      tree v = var;
+	      /* For &X->fld, compute object size only if fld isn't the last
+		 field, as struct { int i; char c[1]; } is often used instead
+		 of flexible array member.  */
+	      while (v && v != pt_var)
+		switch (TREE_CODE (v))
+		  {
+		  case ARRAY_REF:
+		    if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))
+			&& TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST)
+		      {
+			tree domain
+			  = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)));
+			if (domain
+			    && TYPE_MAX_VALUE (domain)
+			    && TREE_CODE (TYPE_MAX_VALUE (domain))
+			       == INTEGER_CST
+			    && tree_int_cst_lt (TREE_OPERAND (v, 1),
+						TYPE_MAX_VALUE (domain)))
+			  {
+			    v = NULL_TREE;
+			    break;
+			  }
+		      }
+		    v = TREE_OPERAND (v, 0);
+		    break;
+		  case REALPART_EXPR:
+		  case IMAGPART_EXPR:
+		    v = NULL_TREE;
+		    break;
+		  case COMPONENT_REF:
+		    if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
+		      {
+			v = NULL_TREE;
+			break;
+		      }
+		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			  != UNION_TYPE
+			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			  != QUAL_UNION_TYPE)
+			break;
+		      else
+			v = TREE_OPERAND (v, 0);
+		    if (TREE_CODE (v) == COMPONENT_REF
+			&& TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			   == RECORD_TYPE)
+		      {
+			tree fld_chain = TREE_CHAIN (TREE_OPERAND (v, 1));
+			for (; fld_chain; fld_chain = TREE_CHAIN (fld_chain))
+			  if (TREE_CODE (fld_chain) == FIELD_DECL)
+			    break;
+
+			if (fld_chain)
+			  {
+			    v = NULL_TREE;
+			    break;
+			  }
+			v = TREE_OPERAND (v, 0);
+		      }
+		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			  != UNION_TYPE
+			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			  != QUAL_UNION_TYPE)
+			break;
+		      else
+			v = TREE_OPERAND (v, 0);
+		    if (v != pt_var)
+		      v = NULL_TREE;
+		    else
+		      v = pt_var;
+		    break;
+		  default:
+		    v = pt_var;
+		    break;
+		  }
+	      if (v == pt_var)
 		var = pt_var;
 	    }
-	  else
-	    var = pt_var;
-
-	  bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
-	  if (bytes != error_mark_node)
-	    {
-	      if (TREE_CODE (bytes) == INTEGER_CST
-		  && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes))
-		bytes = size_zero_node;
-	      else
-		bytes = size_binop (MINUS_EXPR,
-				    TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes);
-	    }
 	}
       else
-	bytes = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
+	var = pt_var;
 
-      if (host_integerp (bytes, 1))
-	return tree_low_cst (bytes, 1);
+      if (var != pt_var)
+	var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
+      else if (!pt_var_size)
+	return unknown[object_size_type];
+      else
+	var_size = pt_var_size;
+      bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
+      if (bytes != error_mark_node)
+	{
+	  if (TREE_CODE (bytes) == INTEGER_CST
+	      && tree_int_cst_lt (var_size, bytes))
+	    bytes = size_zero_node;
+	  else
+	    bytes = size_binop (MINUS_EXPR, var_size, bytes);
+	}
+      if (var != pt_var
+	  && pt_var_size
+	  && TREE_CODE (pt_var) == INDIRECT_REF
+	  && bytes != error_mark_node)
+	{
+	  tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
+	  if (bytes2 != error_mark_node)
+	    {
+	      if (TREE_CODE (bytes2) == INTEGER_CST
+		  && tree_int_cst_lt (pt_var_size, bytes2))
+		bytes2 = size_zero_node;
+	      else
+		bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
+	      bytes = size_binop (MIN_EXPR, bytes, bytes2);
+	    }
+	}
     }
+  else if (!pt_var_size)
+    return unknown[object_size_type];
+  else
+    bytes = pt_var_size;
+
+  if (host_integerp (bytes, 1))
+    return tree_low_cst (bytes, 1);
 
   return unknown[object_size_type];
 }
@@ -246,7 +381,7 @@
       if (TREE_CHAIN (p))
         arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1;
     }
- 
+
   if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
     switch (DECL_FUNCTION_CODE (callee))
       {
@@ -262,10 +397,10 @@
 
   if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call)
       || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST
-      || (arg2 >= 0 
+      || (arg2 >= 0
 	  && (arg2 >= (int)gimple_call_num_args (call)
 	      || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST)))
-    return unknown[object_size_type];	  
+    return unknown[object_size_type];
 
   if (arg2 >= 0)
     bytes = size_binop (MULT_EXPR,
@@ -331,11 +466,11 @@
     init_offset_limit ();
 
   if (TREE_CODE (ptr) == ADDR_EXPR)
-    return addr_object_size (ptr, object_size_type);
+    return addr_object_size (NULL, ptr, object_size_type);
 
   if (TREE_CODE (ptr) == SSA_NAME
-	   && POINTER_TYPE_P (TREE_TYPE (ptr))
-	   && object_sizes[object_size_type] != NULL)
+      && POINTER_TYPE_P (TREE_TYPE (ptr))
+      && object_sizes[object_size_type] != NULL)
     {
       if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
 	{
@@ -476,7 +611,7 @@
 	      || !POINTER_TYPE_P (TREE_TYPE (value)));
 
   if (TREE_CODE (value) == ADDR_EXPR)
-    bytes = addr_object_size (value, object_size_type);
+    bytes = addr_object_size (osi, value, object_size_type);
   else
     bytes = unknown[object_size_type];
 
@@ -632,7 +767,7 @@
 	  unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
 
           /* op0 will be ADDR_EXPR here.  */
-	  bytes = compute_builtin_object_size (op0, object_size_type);
+	  bytes = addr_object_size (osi, op0, object_size_type);
 	  if (bytes == unknown[object_size_type])
 	    ;
 	  else if (off > offset_limit)
@@ -976,7 +1111,7 @@
     {
       tree basevar = gimple_assign_rhs1 (stmt);
       tree cst = gimple_assign_rhs2 (stmt);
-	    
+
       gcc_assert (TREE_CODE (cst) == INTEGER_CST);
 
       if (integer_zerop (cst))
@@ -1111,8 +1246,8 @@
   NULL,					/* sub */
   NULL,					/* next */
   0,					/* static_pass_number */
-  0,					/* tv_id */
-  PROP_cfg | PROP_ssa | PROP_alias,	/* properties_required */
+  TV_NONE,				/* tv_id */
+  PROP_cfg | PROP_ssa,			/* properties_required */
   0,					/* properties_provided */
   0,					/* properties_destroyed */
   0,					/* todo_flags_start */