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
break;
case tcc_exceptional: /* something random, like an identifier. */
- if (code == IDENTIFIER_NODE)
- kind = id_kind;
- else if (code == TREE_VEC)
- kind = vec_kind;
- else if (code == TREE_BINFO)
- kind = binfo_kind;
- else if (code == PHI_NODE)
- kind = phi_kind;
- else if (code == SSA_NAME)
- kind = ssa_name_kind;
- else if (code == BLOCK)
- kind = b_kind;
- else
- kind = x_kind;
+ switch (code)
+ {
+ case IDENTIFIER_NODE:
+ kind = id_kind;
+ break;
+
+ case TREE_VEC:;
+ kind = vec_kind;
+ break;
+
+ case TREE_BINFO:
+ kind = binfo_kind;
+ break;
+
+ case PHI_NODE:
+ kind = phi_kind;
+ break;
+
+ case SSA_NAME:
+ kind = ssa_name_kind;
+ break;
+
+ case BLOCK:
+ kind = b_kind;
+ break;
+
+ default:
+ kind = x_kind;
+ break;
+ }
break;
+
+ default:
+ gcc_unreachable ();
}
tree_node_counts[(int) kind]++;
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);
+
+ 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;
- t = make_node (INTEGER_CST);
+ TREE_INT_CST_LOW (int_cst_node) = low;
+ TREE_INT_CST_HIGH (int_cst_node) = hi;
+ TREE_TYPE (int_cst_node) = type;
- TREE_INT_CST_LOW (t) = low;
- TREE_INT_CST_HIGH (t) = hi;
- TREE_TYPE (t) = 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))
&& ! DECL_NON_ADDR_CONST_P (arg)
? arg : NULL);
+ case CONST_DECL:
+ return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
+ ? arg : NULL);
+
case CONSTRUCTOR:
return TREE_STATIC (arg) ? arg : NULL;
}
/* Now see what's inside. If it's an INDIRECT_REF, copy our properties from
- it. If it's a decl, it's invariant and constant if the decl is static.
- It's also invariant if it's a decl in the current function. (Taking the
- address of a volatile variable is not volatile.) If it's a constant,
- the address is both invariant and constant. Otherwise it's neither. */
+ the address, since &(*a)->b is a form of addition. If it's a decl, it's
+ invariant and constant if the decl is static. It's also invariant if it's
+ a decl in the current function. Taking the address of a volatile variable
+ is not volatile. If it's a constant, the address is both invariant and
+ constant. Otherwise it's neither. */
if (TREE_CODE (node) == INDIRECT_REF)
- {
- /* If this is &((T*)0)->field, then this is a form of addition. */
- if (TREE_CODE (TREE_OPERAND (node, 0)) != INTEGER_CST)
- UPDATE_TITCSE (node);
- }
+ UPDATE_TITCSE (TREE_OPERAND (node, 0));
else if (DECL_P (node))
{
if (staticp (node))
{
case VOID_TYPE:
case COMPLEX_TYPE:
- case VECTOR_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
return 1;
+ case VECTOR_TYPE:
+ return TYPE_VECTOR_SUBPARTS (a->type) == TYPE_VECTOR_SUBPARTS (b->type);
+
case ENUMERAL_TYPE:
if (TYPE_VALUES (a->type) != TYPE_VALUES (b->type)
&& !(TYPE_VALUES (a->type)
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);
}
{
tree t = make_node (VECTOR_TYPE);
- TREE_TYPE (t) = innertype;
+ TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype);
TYPE_VECTOR_SUBPARTS (t) = nunits;
TYPE_MODE (t) = mode;
+ TYPE_READONLY (t) = TYPE_READONLY (innertype);
+ TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype);
+
layout_type (t);
{
TYPE_UID (rt) = TYPE_UID (t);
}
+ /* Build our main variant, based on the main variant of the inner type. */
+ if (TYPE_MAIN_VARIANT (innertype) != innertype)
+ {
+ tree innertype_main_variant = TYPE_MAIN_VARIANT (innertype);
+ unsigned int hash = TYPE_HASH (innertype_main_variant);
+ TYPE_MAIN_VARIANT (t)
+ = type_hash_canon (hash, make_vector_type (innertype_main_variant,
+ nunits, mode));
+ }
+
return t;
}
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"