OSDN Git Service

* gcc.dg/uninit-H.c: Define ASM for Xtensa targets.
[pf3gnuchains/gcc-fork.git] / gcc / tree.c
index b132571..32ec8a5 100644 (file)
@@ -125,9 +125,16 @@ struct type_hash GTY(())
 static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
      htab_t type_hash_table;
 
+/* Hash table and temporary node for larger integer const values.  */
+static GTY (()) tree int_cst_node;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
+     htab_t int_cst_hash_table;
+
 static void set_type_quals (tree, int);
 static int type_hash_eq (const void *, const void *);
 static hashval_t type_hash_hash (const void *);
+static hashval_t int_cst_hash_hash (const void *);
+static int int_cst_hash_eq (const void *, const void *);
 static void print_type_hash_statistics (void);
 static tree make_vector_type (tree, int, enum machine_mode);
 static int type_hash_marked_p (const void *);
@@ -145,6 +152,9 @@ init_ttree (void)
   /* Initialize the hash table of types.  */
   type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
                                     type_hash_eq, 0);
+  int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
+                                       int_cst_hash_eq, NULL);
+  int_cst_node = make_node (INTEGER_CST);
 }
 
 \f
@@ -522,8 +532,38 @@ build_int_cst_type (tree type, HOST_WIDE_INT low)
   return ret;
 }
 
+/* These are the hash table functions for the hash table of INTEGER_CST
+   nodes of a sizetype.  */
+
+/* Return the hash code code X, an INTEGER_CST.  */
+
+static hashval_t
+int_cst_hash_hash (const void *x)
+{
+  tree t = (tree) x;
+
+  return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
+         ^ htab_hash_pointer (TREE_TYPE (t)));
+}
+
+/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
+   is the same as that given by *Y, which is the same.  */
+
+static int
+int_cst_hash_eq (const void *x, const void *y)
+{
+  tree xt = (tree) x;
+  tree yt = (tree) y;
+
+  return (TREE_TYPE (xt) == TREE_TYPE (yt)
+         && TREE_INT_CST_HIGH (xt) == TREE_INT_CST_HIGH (yt)
+         && TREE_INT_CST_LOW (xt) == TREE_INT_CST_LOW (yt));
+}
+
 /* Create an INT_CST node of TYPE and value HI:LOW.  If TYPE is NULL,
-   integer_type_node is used.  */
+   integer_type_node is used.  The returned node is always shared.
+   For small integers we use a per-type vector cache, for larger ones
+   we use a single hash table.  */
 
 tree
 build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
@@ -580,6 +620,7 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
 
   if (ix >= 0)
     {
+      /* Look for it in the type's vector of small shared ints.  */
       if (!TYPE_CACHED_VALUES_P (type))
        {
          TYPE_CACHED_VALUES_P (type) = 1;
@@ -593,22 +634,77 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
          gcc_assert (TREE_TYPE (t) == type);
          gcc_assert (TREE_INT_CST_LOW (t) == low);
          gcc_assert (TREE_INT_CST_HIGH (t) == hi);
-         return t;
        }
-    }
+      else
+       {
+         /* Create a new shared int.  */
+         t = make_node (INTEGER_CST);
 
-  t = make_node (INTEGER_CST);
+         TREE_INT_CST_LOW (t) = low;
+         TREE_INT_CST_HIGH (t) = hi;
+         TREE_TYPE (t) = type;
+         
+         TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
+       }
+    }
+  else
+    {
+      /* Use the cache of larger shared ints.  */
+      void **slot;
 
-  TREE_INT_CST_LOW (t) = low;
-  TREE_INT_CST_HIGH (t) = hi;
-  TREE_TYPE (t) = type;
+      TREE_INT_CST_LOW (int_cst_node) = low;
+      TREE_INT_CST_HIGH (int_cst_node) = hi;
+      TREE_TYPE (int_cst_node) = type;
 
-  if (ix >= 0)
-    TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
+      slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
+      t = *slot;
+      if (!t)
+       {
+         /* Insert this one into the hash table.  */
+         t = int_cst_node;
+         *slot = t;
+         /* Make a new node for next time round.  */
+         int_cst_node = make_node (INTEGER_CST);
+       }
+    }
 
   return t;
 }
 
+/* Builds an integer constant in TYPE such that lowest BITS bits are ones
+   and the rest are zeros.  */
+
+tree
+build_low_bits_mask (tree type, unsigned bits)
+{
+  unsigned HOST_WIDE_INT low;
+  HOST_WIDE_INT high;
+  unsigned HOST_WIDE_INT all_ones = ~(unsigned HOST_WIDE_INT) 0;
+
+  gcc_assert (bits <= TYPE_PRECISION (type));
+
+  if (bits == TYPE_PRECISION (type)
+      && !TYPE_UNSIGNED (type))
+    {
+      /* Sign extended all-ones mask.  */
+      low = all_ones;
+      high = -1;
+    }
+  else if (bits <= HOST_BITS_PER_WIDE_INT)
+    {
+      low = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
+      high = 0;
+    }
+  else
+    {
+      bits -= HOST_BITS_PER_WIDE_INT;
+      low = all_ones;
+      high = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
+    }
+
+  return build_int_cst_wide (type, low, high);
+}
+
 /* Checks that X is integer constant that can be expressed in (unsigned)
    HOST_WIDE_INT without loss of precision.  */
 
@@ -1477,11 +1573,10 @@ staticp (tree arg)
   switch (TREE_CODE (arg))
     {
     case FUNCTION_DECL:
-      /* Nested functions aren't static, since taking their address
-        involves a trampoline.  */
-      return ((decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
-             && ! DECL_NON_ADDR_CONST_P (arg)
-             ? arg : NULL);
+      /* Nested functions are static, even though taking their address will
+        involve a trampoline as we unnest the nested function and create
+        the trampoline on the tree level.  */
+      return arg;
 
     case VAR_DECL:
       return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
@@ -3959,7 +4054,7 @@ associative_tree_code (enum tree_code code)
   return false;
 }
 
-/* Return true if CODE represents an commutative tree code.  Otherwise
+/* Return true if CODE represents a commutative tree code.  Otherwise
    return false.  */
 bool
 commutative_tree_code (enum tree_code code)
@@ -4333,9 +4428,12 @@ build_array_type (tree elt_type, tree index_type)
   t = make_node (ARRAY_TYPE);
   TREE_TYPE (t) = elt_type;
   TYPE_DOMAIN (t) = index_type;
-
+  
   if (index_type == 0)
-    return t;
+    {
+      layout_type (t);
+      return t;
+    }
 
   hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
   hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
@@ -5304,8 +5402,9 @@ get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size)
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 
 /* Complain that the tree code of NODE does not match the expected 0
-   terminated list of trailing codes. FILE, LINE, and FUNCTION are of
-   the caller.  */
+   terminated list of trailing codes. The trailing code list can be
+   empty, for a more vague error message.  FILE, LINE, and FUNCTION
+   are of the caller.  */
 
 void
 tree_check_failed (const tree node, const char *file,
@@ -5320,22 +5419,27 @@ tree_check_failed (const tree node, const char *file,
   while ((code = va_arg (args, int)))
     length += 4 + strlen (tree_code_name[code]);
   va_end (args);
-  va_start (args, function);
-  buffer = alloca (length);
-  length = 0;
-  while ((code = va_arg (args, int)))
+  if (length)
     {
-      if (length)
+      va_start (args, function);
+      length += strlen ("expected ");
+      buffer = alloca (length);
+      length = 0;
+      while ((code = va_arg (args, int)))
        {
-         strcpy (buffer + length, " or ");
-         length += 4;
+         const char *prefix = length ? " or " : "expected ";
+         
+         strcpy (buffer + length, prefix);
+         length += strlen (prefix);
+         strcpy (buffer + length, tree_code_name[code]);
+         length += strlen (tree_code_name[code]);
        }
-      strcpy (buffer + length, tree_code_name[code]);
-      length += strlen (tree_code_name[code]);
+      va_end (args);
     }
-  va_end (args);
+  else
+    buffer = (char *)"unexpected node";
 
-  internal_error ("tree check: expected %s, have %s in %s, at %s:%d",
+  internal_error ("tree check: %s, have %s in %s, at %s:%d",
                  buffer, tree_code_name[TREE_CODE (node)],
                  function, trim_filename (file), line);
 }
@@ -5930,7 +6034,7 @@ tree_fold_gcd (tree a, tree b)
 
   while (1)
     {
-      a_mod_b = fold (build2 (CEIL_MOD_EXPR, type, a, b));
+      a_mod_b = fold (build2 (FLOOR_MOD_EXPR, type, a, b));
 
       if (!TREE_INT_CST_LOW (a_mod_b)
          && !TREE_INT_CST_HIGH (a_mod_b))
@@ -5957,4 +6061,76 @@ signed_type_for (tree type)
   return lang_hooks.types.signed_type (type);
 }
 
+/* Returns the largest value obtainable by casting something in INNER type to
+   OUTER type.  */
+
+tree
+upper_bound_in_type (tree outer, tree inner)
+{
+  unsigned HOST_WIDE_INT lo, hi;
+  unsigned bits = TYPE_PRECISION (inner);
+
+  if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
+    {
+      /* Zero extending in these cases.  */
+      if (bits <= HOST_BITS_PER_WIDE_INT)
+       {
+         hi = 0;
+         lo = (~(unsigned HOST_WIDE_INT) 0)
+                 >> (HOST_BITS_PER_WIDE_INT - bits);
+       }
+      else
+       {
+         hi = (~(unsigned HOST_WIDE_INT) 0)
+                 >> (2 * HOST_BITS_PER_WIDE_INT - bits);
+         lo = ~(unsigned HOST_WIDE_INT) 0;
+       }
+    }
+  else
+    {
+      /* Sign extending in these cases.  */
+      if (bits <= HOST_BITS_PER_WIDE_INT)
+       {
+         hi = 0;
+         lo = (~(unsigned HOST_WIDE_INT) 0)
+                 >> (HOST_BITS_PER_WIDE_INT - bits) >> 1;
+       }
+      else
+       {
+         hi = (~(unsigned HOST_WIDE_INT) 0)
+                 >> (2 * HOST_BITS_PER_WIDE_INT - bits) >> 1;
+         lo = ~(unsigned HOST_WIDE_INT) 0;
+       }
+    }
+
+  return fold_convert (outer,
+                      build_int_cst_wide (inner, lo, hi));
+}
+
+/* Returns the smallest value obtainable by casting something in INNER type to
+   OUTER type.  */
+
+tree
+lower_bound_in_type (tree outer, tree inner)
+{
+  unsigned HOST_WIDE_INT lo, hi;
+  unsigned bits = TYPE_PRECISION (inner);
+
+  if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
+    lo = hi = 0;
+  else if (bits <= HOST_BITS_PER_WIDE_INT)
+    {
+      hi = ~(unsigned HOST_WIDE_INT) 0;
+      lo = (~(unsigned HOST_WIDE_INT) 0) << (bits - 1);
+    }
+  else
+    {
+      hi = (~(unsigned HOST_WIDE_INT) 0) << (bits - HOST_BITS_PER_WIDE_INT - 1);
+      lo = 0;
+    }
+
+  return fold_convert (outer,
+                      build_int_cst_wide (inner, lo, hi));
+}
+
 #include "gt-tree.h"