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 *);
/* 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
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)
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;
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. */
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))
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)
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);
#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,
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);
}
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))
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"