/* Language-independent node constructors for parse phase of GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
return inner;
}
-/* Returns the index of the first non-tree operand for CODE, or the number
- of operands if all are trees. */
-
-int
-first_rtl_op (enum tree_code code)
-{
- switch (code)
- {
- default:
- return TREE_CODE_LENGTH (code);
- }
-}
-
/* Return which tree structure is used by T. */
enum tree_node_structure_enum
break;
}
- switch (first_rtl_op (code))
+ switch (TREE_CODE_LENGTH (code))
{
case 1:
return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
case METHOD_TYPE:
case FILE_TYPE:
case FUNCTION_TYPE:
+ case VECTOR_TYPE:
return false;
case INTEGER_TYPE:
|| CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
case ARRAY_TYPE:
- case SET_TYPE:
- case VECTOR_TYPE:
/* We're already checked the component type (TREE_TYPE), so just check
the index type. */
return type_contains_placeholder_p (TYPE_DOMAIN (type));
case tcc_comparison:
case tcc_expression:
case tcc_reference:
- switch (first_rtl_op (code))
+ switch (TREE_CODE_LENGTH (code))
{
case 0:
return exp;
case tcc_expression:
case tcc_reference:
case tcc_statement:
- switch (first_rtl_op (code))
+ switch (TREE_CODE_LENGTH (code))
{
case 0:
return exp;
{
if (staticp (node))
;
- else if (decl_function_context (node) == current_function_decl)
+ else if (decl_function_context (node) == current_function_decl
+ /* Addresses of thread-local variables are invariant. */
+ || (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node)))
tc = false;
else
ti = tc = false;
TREE_COMPLEXITY (t) = 0;
TREE_OPERAND (t, 0) = node;
TREE_BLOCK (t) = NULL_TREE;
- if (node && !TYPE_P (node) && first_rtl_op (code) != 0)
+ if (node && !TYPE_P (node))
{
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (node);
TREE_READONLY (t) = TREE_READONLY (node);
#define PROCESS_ARG(N) \
do { \
TREE_OPERAND (t, N) = arg##N; \
- if (arg##N &&!TYPE_P (arg##N) && fro > N) \
+ if (arg##N &&!TYPE_P (arg##N)) \
{ \
if (TREE_SIDE_EFFECTS (arg##N)) \
side_effects = 1; \
{
bool constant, read_only, side_effects, invariant;
tree t;
- int fro;
gcc_assert (TREE_CODE_LENGTH (code) == 2);
result based on those same flags for the arguments. But if the
arguments aren't really even `tree' expressions, we shouldn't be trying
to do this. */
- fro = first_rtl_op (code);
/* Expressions without side effects may be constant if their
arguments are as well. */
{
bool constant, read_only, side_effects, invariant;
tree t;
- int fro;
gcc_assert (TREE_CODE_LENGTH (code) == 3);
t = make_node_stat (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
- fro = first_rtl_op (code);
-
side_effects = TREE_SIDE_EFFECTS (t);
PROCESS_ARG(0);
{
bool constant, read_only, side_effects, invariant;
tree t;
- int fro;
gcc_assert (TREE_CODE_LENGTH (code) == 4);
t = make_node_stat (code PASS_MEM_STAT);
TREE_TYPE (t) = tt;
- fro = first_rtl_op (code);
-
side_effects = TREE_SIDE_EFFECTS (t);
PROCESS_ARG(0);
return ttype;
}
+
/* Return nonzero if IDENT is a valid name for attribute ATTR,
or zero if not.
`text'. One might then also require attribute lists to be stored in
their canonicalized form. */
-int
-is_attribute_p (const char *attr, tree ident)
+static int
+is_attribute_with_length_p (const char *attr, int attr_len, tree ident)
{
- int ident_len, attr_len;
+ int ident_len;
const char *p;
if (TREE_CODE (ident) != IDENTIFIER_NODE)
return 0;
-
- if (strcmp (attr, IDENTIFIER_POINTER (ident)) == 0)
- return 1;
-
+
p = IDENTIFIER_POINTER (ident);
- ident_len = strlen (p);
- attr_len = strlen (attr);
+ ident_len = IDENTIFIER_LENGTH (ident);
+
+ if (ident_len == attr_len
+ && strcmp (attr, p) == 0)
+ return 1;
/* If ATTR is `__text__', IDENT must be `text'; and vice versa. */
if (attr[0] == '_')
return 0;
}
+/* Return nonzero if IDENT is a valid name for attribute ATTR,
+ or zero if not.
+
+ We try both `text' and `__text__', ATTR may be either one. */
+
+int
+is_attribute_p (const char *attr, tree ident)
+{
+ return is_attribute_with_length_p (attr, strlen (attr), ident);
+}
+
/* Given an attribute name and a list of attributes, return a pointer to the
attribute's list element if the attribute is part of the list, or NULL_TREE
if not found. If the attribute appears more than once, this only
lookup_attribute (const char *attr_name, tree list)
{
tree l;
+ size_t attr_len = strlen (attr_name);
for (l = list; l; l = TREE_CHAIN (l))
{
gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
- if (is_attribute_p (attr_name, TREE_PURPOSE (l)))
+ if (is_attribute_with_length_p (attr_name, attr_len, TREE_PURPOSE (l)))
return l;
}
{
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)
TYPE_ARG_TYPES (b->type)))));
case ARRAY_TYPE:
- case SET_TYPE:
return TYPE_DOMAIN (a->type) == TYPE_DOMAIN (b->type);
case RECORD_TYPE:
for (; t; t = TREE_CHAIN (t))
val = iterative_hash_expr (TREE_VALUE (t), val);
return val;
+ case FUNCTION_DECL:
+ /* When referring to a built-in FUNCTION_DECL, use the
+ __builtin__ form. Otherwise nodes that compare equal
+ according to operand_equal_p might get different
+ hash codes. */
+ if (DECL_BUILT_IN (t))
+ {
+ val = iterative_hash_pointer (built_in_decls[DECL_FUNCTION_CODE (t)],
+ val);
+ return val;
+ }
+ /* else FALL THROUGH */
default:
class = TREE_CODE_CLASS (code);
if (class == tcc_declaration)
{
- /* Decls we can just compare by pointer. */
+ /* Otherwise, we can just compare decls by pointer. */
val = iterative_hash_pointer (t, val);
}
else
val = iterative_hash_hashval_t (two, val);
}
else
- for (i = first_rtl_op (code) - 1; i >= 0; --i)
+ for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; --i)
val = iterative_hash_expr (TREE_OPERAND (t, i), val);
}
return val;
/* Perform some generic filtering first, which may allow making a decision
even if the bounds are not constant. First, negative integers never fit
in unsigned types, */
- if ((TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
- /* Also, unsigned integers with top bit set never fit signed types. */
- || (! TYPE_UNSIGNED (type)
- && TYPE_UNSIGNED (TREE_TYPE (c)) && tree_int_cst_msb (c)))
+ if (TYPE_UNSIGNED (type) && tree_int_cst_sgn (c) < 0)
+ return 0;
+
+ /* Second, narrower types always fit in wider ones. */
+ if (TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (c)))
+ return 1;
+
+ /* Third, unsigned integers with top bit set never fit signed types. */
+ if (! TYPE_UNSIGNED (type)
+ && TYPE_UNSIGNED (TREE_TYPE (c))
+ && tree_int_cst_msb (c))
return 0;
/* If at least one bound of the type is a constant integer, we can check
/* Or to force_fit_type, if nothing else. */
else
{
- c = copy_node (c);
- TREE_TYPE (c) = type;
- c = force_fit_type (c, -1, false, false);
- return !TREE_OVERFLOW (c);
+ tree n = copy_node (c);
+ TREE_TYPE (n) = type;
+ n = force_fit_type (n, -1, false, false);
+ return TREE_INT_CST_HIGH (n) == TREE_INT_CST_HIGH (c)
+ && TREE_INT_CST_LOW (n) == TREE_INT_CST_LOW (c);
}
}
case POINTER_TYPE:
case REFERENCE_TYPE:
case ARRAY_TYPE:
- case SET_TYPE:
case VECTOR_TYPE:
if (variably_modified_type_p (TREE_TYPE (type), fn))
return true;
{
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;
}
if (elt == NULL_TREE)
return true;
- /* A set is empty only if it has no elements. */
- if (TREE_CODE (TREE_TYPE (init)) == SET_TYPE)
- return false;
-
for (; elt ; elt = TREE_CHAIN (elt))
if (! initializer_zerop (TREE_VALUE (elt)))
return false;
return lang_hooks.types.signed_type (type);
}
-/* Return the LABEL_DECL associated with T, which must be a
- CASE_LABEL_EXPR. This will walk through any CASE_LABEL_EXPRs
- appearing in operand 2 until it finds a CASE_LABEL_EXPR with
- a LABEL_DECL in operand 2. */
-
-tree
-get_case_label (tree t)
-{
- while (TREE_CODE (CASE_LEADER_OR_LABEL (t)) == CASE_LABEL_EXPR)
- t = CASE_LEADER_OR_LABEL (t);
- return CASE_LEADER_OR_LABEL (t);
-}
-
/* Returns the largest value obtainable by casting something in INNER type to
OUTER type. */
build_int_cst_wide (inner, lo, hi));
}
+/* Return nonzero if two operands that are suitable for PHI nodes are
+ necessarily equal. Specifically, both ARG0 and ARG1 must be either
+ SSA_NAME or invariant. Note that this is strictly an optimization.
+ That is, callers of this function can directly call operand_equal_p
+ and get the same result, only slower. */
+
+int
+operand_equal_for_phi_arg_p (tree arg0, tree arg1)
+{
+ if (arg0 == arg1)
+ return 1;
+ if (TREE_CODE (arg0) == SSA_NAME || TREE_CODE (arg1) == SSA_NAME)
+ return 0;
+ return operand_equal_p (arg0, arg1, 0);
+}
+
#include "gt-tree.h"