+
+
+/* Returns true if it is possible to prove that the index of
+ an array access REF (an ARRAY_REF expression) falls into the
+ array bounds. */
+
+bool
+in_array_bounds_p (tree ref)
+{
+ tree idx = TREE_OPERAND (ref, 1);
+ tree min, max;
+
+ if (TREE_CODE (idx) != INTEGER_CST)
+ return false;
+
+ min = array_ref_low_bound (ref);
+ max = array_ref_up_bound (ref);
+ if (!min
+ || !max
+ || TREE_CODE (min) != INTEGER_CST
+ || TREE_CODE (max) != INTEGER_CST)
+ return false;
+
+ if (tree_int_cst_lt (idx, min)
+ || tree_int_cst_lt (max, idx))
+ return false;
+
+ return true;
+}
+
+/* Returns true if it is possible to prove that the range of
+ an array access REF (an ARRAY_RANGE_REF expression) falls
+ into the array bounds. */
+
+bool
+range_in_array_bounds_p (tree ref)
+{
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (ref));
+ tree range_min, range_max, min, max;
+
+ range_min = TYPE_MIN_VALUE (domain_type);
+ range_max = TYPE_MAX_VALUE (domain_type);
+ if (!range_min
+ || !range_max
+ || TREE_CODE (range_min) != INTEGER_CST
+ || TREE_CODE (range_max) != INTEGER_CST)
+ return false;
+
+ min = array_ref_low_bound (ref);
+ max = array_ref_up_bound (ref);
+ if (!min
+ || !max
+ || TREE_CODE (min) != INTEGER_CST
+ || TREE_CODE (max) != INTEGER_CST)
+ return false;
+
+ if (tree_int_cst_lt (range_min, min)
+ || tree_int_cst_lt (max, range_max))
+ return false;
+
+ return true;
+}
+
+/* Return true if T (assumed to be a DECL) must be assigned a memory
+ location. */
+
+bool
+needs_to_live_in_memory (const_tree t)
+{
+ if (TREE_CODE (t) == SSA_NAME)
+ t = SSA_NAME_VAR (t);
+
+ return (TREE_ADDRESSABLE (t)
+ || is_global_var (t)
+ || (TREE_CODE (t) == RESULT_DECL
+ && aggregate_value_p (t, current_function_decl)));
+}
+
+/* There are situations in which a language considers record types
+ compatible which have different field lists. Decide if two fields
+ are compatible. It is assumed that the parent records are compatible. */
+
+bool
+fields_compatible_p (const_tree f1, const_tree f2)
+{
+ if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1),
+ DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST))
+ return false;
+
+ if (!operand_equal_p (DECL_FIELD_OFFSET (f1),
+ DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST))
+ return false;
+
+ if (!types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+ return false;
+
+ return true;
+}
+
+/* Locate within RECORD a field that is compatible with ORIG_FIELD. */
+
+tree
+find_compatible_field (tree record, tree orig_field)
+{
+ tree f;
+
+ for (f = TYPE_FIELDS (record); f ; f = TREE_CHAIN (f))
+ if (TREE_CODE (f) == FIELD_DECL
+ && fields_compatible_p (f, orig_field))
+ return f;
+
+ /* ??? Why isn't this on the main fields list? */
+ f = TYPE_VFIELD (record);
+ if (f && TREE_CODE (f) == FIELD_DECL
+ && fields_compatible_p (f, orig_field))
+ return f;
+
+ /* ??? We should abort here, but Java appears to do Bad Things
+ with inherited fields. */
+ return orig_field;
+}
+
+/* Return value of a constant X and sign-extend it. */
+
+HOST_WIDE_INT
+int_cst_value (const_tree x)
+{
+ unsigned bits = TYPE_PRECISION (TREE_TYPE (x));
+ unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x);
+
+ /* Make sure the sign-extended value will fit in a HOST_WIDE_INT. */
+ gcc_assert (TREE_INT_CST_HIGH (x) == 0
+ || TREE_INT_CST_HIGH (x) == -1);
+
+ if (bits < HOST_BITS_PER_WIDE_INT)
+ {
+ bool negative = ((val >> (bits - 1)) & 1) != 0;
+ if (negative)
+ val |= (~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1;
+ else
+ val &= ~((~(unsigned HOST_WIDE_INT) 0) << (bits - 1) << 1);
+ }
+
+ return val;
+}
+
+/* If TYPE is an integral type, return an equivalent type which is
+ unsigned iff UNSIGNEDP is true. If TYPE is not an integral type,
+ return TYPE itself. */
+
+tree
+signed_or_unsigned_type_for (int unsignedp, tree type)
+{
+ tree t = type;
+ if (POINTER_TYPE_P (type))
+ t = size_type_node;
+
+ if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp)
+ return t;
+
+ return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp);
+}
+
+/* Returns unsigned variant of TYPE. */
+
+tree
+unsigned_type_for (tree type)
+{
+ return signed_or_unsigned_type_for (1, type);
+}
+
+/* Returns signed variant of TYPE. */
+
+tree
+signed_type_for (tree type)
+{
+ return signed_or_unsigned_type_for (0, 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 int det = 0;
+ unsigned oprec = TYPE_PRECISION (outer);
+ unsigned iprec = TYPE_PRECISION (inner);
+ unsigned prec;
+
+ /* Compute a unique number for every combination. */
+ det |= (oprec > iprec) ? 4 : 0;
+ det |= TYPE_UNSIGNED (outer) ? 2 : 0;
+ det |= TYPE_UNSIGNED (inner) ? 1 : 0;
+
+ /* Determine the exponent to use. */
+ switch (det)
+ {
+ case 0:
+ case 1:
+ /* oprec <= iprec, outer: signed, inner: don't care. */
+ prec = oprec - 1;
+ break;
+ case 2:
+ case 3:
+ /* oprec <= iprec, outer: unsigned, inner: don't care. */
+ prec = oprec;
+ break;
+ case 4:
+ /* oprec > iprec, outer: signed, inner: signed. */
+ prec = iprec - 1;
+ break;
+ case 5:
+ /* oprec > iprec, outer: signed, inner: unsigned. */
+ prec = iprec;
+ break;
+ case 6:
+ /* oprec > iprec, outer: unsigned, inner: signed. */
+ prec = oprec;
+ break;
+ case 7:
+ /* oprec > iprec, outer: unsigned, inner: unsigned. */
+ prec = iprec;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Compute 2^^prec - 1. */
+ if (prec <= HOST_BITS_PER_WIDE_INT)
+ {
+ hi = 0;
+ lo = ((~(unsigned HOST_WIDE_INT) 0)
+ >> (HOST_BITS_PER_WIDE_INT - prec));
+ }
+ else
+ {
+ hi = ((~(unsigned HOST_WIDE_INT) 0)
+ >> (2 * HOST_BITS_PER_WIDE_INT - prec));
+ lo = ~(unsigned HOST_WIDE_INT) 0;
+ }
+
+ return build_int_cst_wide (outer, 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 oprec = TYPE_PRECISION (outer);
+ unsigned iprec = TYPE_PRECISION (inner);
+
+ /* If OUTER type is unsigned, we can definitely cast 0 to OUTER type
+ and obtain 0. */
+ if (TYPE_UNSIGNED (outer)
+ /* If we are widening something of an unsigned type, OUTER type
+ contains all values of INNER type. In particular, both INNER
+ and OUTER types have zero in common. */
+ || (oprec > iprec && TYPE_UNSIGNED (inner)))
+ lo = hi = 0;
+ else
+ {
+ /* If we are widening a signed type to another signed type, we
+ want to obtain -2^^(iprec-1). If we are keeping the
+ precision or narrowing to a signed type, we want to obtain
+ -2^(oprec-1). */
+ unsigned prec = oprec > iprec ? iprec : oprec;
+
+ if (prec <= HOST_BITS_PER_WIDE_INT)
+ {
+ hi = ~(unsigned HOST_WIDE_INT) 0;
+ lo = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
+ }
+ else
+ {
+ hi = ((~(unsigned HOST_WIDE_INT) 0)
+ << (prec - HOST_BITS_PER_WIDE_INT - 1));
+ lo = 0;
+ }
+ }
+
+ return build_int_cst_wide (outer, 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 (const_tree arg0, const_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);
+}
+
+/* Returns number of zeros at the end of binary representation of X.
+
+ ??? Use ffs if available? */
+
+tree
+num_ending_zeros (const_tree x)
+{
+ unsigned HOST_WIDE_INT fr, nfr;
+ unsigned num, abits;
+ tree type = TREE_TYPE (x);
+
+ if (TREE_INT_CST_LOW (x) == 0)
+ {
+ num = HOST_BITS_PER_WIDE_INT;
+ fr = TREE_INT_CST_HIGH (x);
+ }
+ else
+ {
+ num = 0;
+ fr = TREE_INT_CST_LOW (x);
+ }
+
+ for (abits = HOST_BITS_PER_WIDE_INT / 2; abits; abits /= 2)
+ {
+ nfr = fr >> abits;
+ if (nfr << abits == fr)
+ {
+ num += abits;
+ fr = nfr;
+ }
+ }
+
+ if (num > TYPE_PRECISION (type))
+ num = TYPE_PRECISION (type);
+
+ return build_int_cst_type (type, num);
+}
+
+
+#define WALK_SUBTREE(NODE) \
+ do \
+ { \
+ result = walk_tree_1 (&(NODE), func, data, pset, lh); \
+ if (result) \
+ return result; \
+ } \
+ while (0)
+
+/* This is a subroutine of walk_tree that walks field of TYPE that are to
+ be walked whenever a type is seen in the tree. Rest of operands and return
+ value are as for walk_tree. */
+
+static tree
+walk_type_fields (tree type, walk_tree_fn func, void *data,
+ struct pointer_set_t *pset, walk_tree_lh lh)
+{
+ tree result = NULL_TREE;
+
+ switch (TREE_CODE (type))
+ {
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ /* We have to worry about mutually recursive pointers. These can't
+ be written in C. They can in Ada. It's pathological, but
+ there's an ACATS test (c38102a) that checks it. Deal with this
+ by checking if we're pointing to another pointer, that one
+ points to another pointer, that one does too, and we have no htab.
+ If so, get a hash table. We check three levels deep to avoid
+ the cost of the hash table if we don't need one. */
+ if (POINTER_TYPE_P (TREE_TYPE (type))
+ && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (type)))
+ && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (TREE_TYPE (type))))
+ && !pset)
+ {
+ result = walk_tree_without_duplicates (&TREE_TYPE (type),
+ func, data);
+ if (result)
+ return result;
+
+ break;
+ }
+
+ /* ... fall through ... */
+
+ case COMPLEX_TYPE:
+ WALK_SUBTREE (TREE_TYPE (type));
+ break;
+
+ case METHOD_TYPE:
+ WALK_SUBTREE (TYPE_METHOD_BASETYPE (type));
+
+ /* Fall through. */
+
+ case FUNCTION_TYPE:
+ WALK_SUBTREE (TREE_TYPE (type));
+ {
+ tree arg;
+
+ /* We never want to walk into default arguments. */
+ for (arg = TYPE_ARG_TYPES (type); arg; arg = TREE_CHAIN (arg))
+ WALK_SUBTREE (TREE_VALUE (arg));
+ }
+ break;
+
+ case ARRAY_TYPE:
+ /* Don't follow this nodes's type if a pointer for fear that
+ we'll have infinite recursion. If we have a PSET, then we
+ need not fear. */
+ if (pset
+ || (!POINTER_TYPE_P (TREE_TYPE (type))
+ && TREE_CODE (TREE_TYPE (type)) != OFFSET_TYPE))
+ WALK_SUBTREE (TREE_TYPE (type));
+ WALK_SUBTREE (TYPE_DOMAIN (type));
+ break;
+
+ case OFFSET_TYPE:
+ WALK_SUBTREE (TREE_TYPE (type));
+ WALK_SUBTREE (TYPE_OFFSET_BASETYPE (type));
+ break;
+
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+/* Apply FUNC to all the sub-trees of TP in a pre-order traversal. FUNC is
+ called with the DATA and the address of each sub-tree. If FUNC returns a
+ non-NULL value, the traversal is stopped, and the value returned by FUNC
+ is returned. If PSET is non-NULL it is used to record the nodes visited,
+ and to avoid visiting a node more than once. */
+
+tree
+walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
+ struct pointer_set_t *pset, walk_tree_lh lh)
+{
+ enum tree_code code;
+ int walk_subtrees;
+ tree result;
+
+#define WALK_SUBTREE_TAIL(NODE) \
+ do \
+ { \
+ tp = & (NODE); \
+ goto tail_recurse; \
+ } \
+ while (0)
+
+ tail_recurse:
+ /* Skip empty subtrees. */
+ if (!*tp)
+ return NULL_TREE;
+
+ /* Don't walk the same tree twice, if the user has requested
+ that we avoid doing so. */
+ if (pset && pointer_set_insert (pset, *tp))
+ return NULL_TREE;
+
+ /* Call the function. */
+ walk_subtrees = 1;
+ result = (*func) (tp, &walk_subtrees, data);
+
+ /* If we found something, return it. */
+ if (result)
+ return result;
+
+ code = TREE_CODE (*tp);
+
+ /* Even if we didn't, FUNC may have decided that there was nothing
+ interesting below this point in the tree. */
+ if (!walk_subtrees)
+ {
+ /* But we still need to check our siblings. */
+ if (code == TREE_LIST)
+ WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
+ else if (code == OMP_CLAUSE)
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+ else
+ return NULL_TREE;
+ }
+
+ if (lh)
+ {
+ result = (*lh) (tp, &walk_subtrees, func, data, pset);
+ if (result || !walk_subtrees)
+ return result;
+ }
+
+ switch (code)
+ {
+ case ERROR_MARK:
+ case IDENTIFIER_NODE:
+ case INTEGER_CST:
+ case REAL_CST:
+ case FIXED_CST:
+ case VECTOR_CST:
+ case STRING_CST:
+ case BLOCK:
+ case PLACEHOLDER_EXPR:
+ case SSA_NAME:
+ case FIELD_DECL:
+ case RESULT_DECL:
+ /* None of these have subtrees other than those already walked
+ above. */
+ break;
+
+ case TREE_LIST:
+ WALK_SUBTREE (TREE_VALUE (*tp));
+ WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
+ break;
+
+ case TREE_VEC:
+ {
+ int len = TREE_VEC_LENGTH (*tp);
+
+ if (len == 0)
+ break;
+
+ /* Walk all elements but the first. */
+ while (--len)
+ WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
+
+ /* Now walk the first one as a tail call. */
+ WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
+ }
+
+ case COMPLEX_CST:
+ WALK_SUBTREE (TREE_REALPART (*tp));
+ WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
+
+ case CONSTRUCTOR:
+ {
+ unsigned HOST_WIDE_INT idx;
+ constructor_elt *ce;
+
+ for (idx = 0;
+ VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (*tp), idx, ce);
+ idx++)
+ WALK_SUBTREE (ce->value);
+ }
+ break;
+
+ case SAVE_EXPR:
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
+
+ case BIND_EXPR:
+ {
+ tree decl;
+ for (decl = BIND_EXPR_VARS (*tp); decl; decl = TREE_CHAIN (decl))
+ {
+ /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk
+ into declarations that are just mentioned, rather than
+ declared; they don't really belong to this part of the tree.
+ And, we can see cycles: the initializer for a declaration
+ can refer to the declaration itself. */
+ WALK_SUBTREE (DECL_INITIAL (decl));
+ WALK_SUBTREE (DECL_SIZE (decl));
+ WALK_SUBTREE (DECL_SIZE_UNIT (decl));
+ }
+ WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp));
+ }
+
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator i;
+ for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i))
+ WALK_SUBTREE (*tsi_stmt_ptr (i));
+ }
+ break;
+
+ case OMP_CLAUSE:
+ switch (OMP_CLAUSE_CODE (*tp))
+ {
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_SHARED:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_COPYIN:
+ case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_IF:
+ case OMP_CLAUSE_NUM_THREADS:
+ case OMP_CLAUSE_SCHEDULE:
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
+ /* FALLTHRU */
+
+ case OMP_CLAUSE_NOWAIT:
+ case OMP_CLAUSE_ORDERED:
+ case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_UNTIED:
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+
+ case OMP_CLAUSE_LASTPRIVATE:
+ WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
+ WALK_SUBTREE (OMP_CLAUSE_LASTPRIVATE_STMT (*tp));
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+
+ case OMP_CLAUSE_COLLAPSE:
+ {
+ int i;
+ for (i = 0; i < 3; i++)
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+ }
+
+ case OMP_CLAUSE_REDUCTION:
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+ break;
+
+ case TARGET_EXPR:
+ {
+ int i, len;
+
+ /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same.
+ But, we only want to walk once. */
+ len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3;
+ for (i = 0; i < len; ++i)
+ WALK_SUBTREE (TREE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len));
+ }
+
+ case CHANGE_DYNAMIC_TYPE_EXPR:
+ WALK_SUBTREE (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*tp));
+ WALK_SUBTREE_TAIL (CHANGE_DYNAMIC_TYPE_LOCATION (*tp));
+
+ case DECL_EXPR:
+ /* If this is a TYPE_DECL, walk into the fields of the type that it's
+ defining. We only want to walk into these fields of a type in this
+ case and not in the general case of a mere reference to the type.
+
+ The criterion is as follows: if the field can be an expression, it
+ must be walked only here. This should be in keeping with the fields
+ that are directly gimplified in gimplify_type_sizes in order for the
+ mark/copy-if-shared/unmark machinery of the gimplifier to work with
+ variable-sized types.
+
+ Note that DECLs get walked as part of processing the BIND_EXPR. */
+ if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL)
+ {
+ tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp));
+ if (TREE_CODE (*type_p) == ERROR_MARK)
+ return NULL_TREE;
+
+ /* Call the function for the type. See if it returns anything or
+ doesn't want us to continue. If we are to continue, walk both
+ the normal fields and those for the declaration case. */
+ result = (*func) (type_p, &walk_subtrees, data);
+ if (result || !walk_subtrees)
+ return result;
+
+ result = walk_type_fields (*type_p, func, data, pset, lh);
+ if (result)
+ return result;
+
+ /* If this is a record type, also walk the fields. */
+ if (TREE_CODE (*type_p) == RECORD_TYPE
+ || TREE_CODE (*type_p) == UNION_TYPE
+ || TREE_CODE (*type_p) == QUAL_UNION_TYPE)
+ {
+ tree field;
+
+ for (field = TYPE_FIELDS (*type_p); field;
+ field = TREE_CHAIN (field))
+ {
+ /* We'd like to look at the type of the field, but we can
+ easily get infinite recursion. So assume it's pointed
+ to elsewhere in the tree. Also, ignore things that
+ aren't fields. */
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ WALK_SUBTREE (DECL_FIELD_OFFSET (field));
+ WALK_SUBTREE (DECL_SIZE (field));
+ WALK_SUBTREE (DECL_SIZE_UNIT (field));
+ if (TREE_CODE (*type_p) == QUAL_UNION_TYPE)
+ WALK_SUBTREE (DECL_QUALIFIER (field));
+ }
+ }
+
+ /* Same for scalar types. */
+ else if (TREE_CODE (*type_p) == BOOLEAN_TYPE
+ || TREE_CODE (*type_p) == ENUMERAL_TYPE
+ || TREE_CODE (*type_p) == INTEGER_TYPE
+ || TREE_CODE (*type_p) == FIXED_POINT_TYPE
+ || TREE_CODE (*type_p) == REAL_TYPE)
+ {
+ WALK_SUBTREE (TYPE_MIN_VALUE (*type_p));
+ WALK_SUBTREE (TYPE_MAX_VALUE (*type_p));
+ }
+
+ WALK_SUBTREE (TYPE_SIZE (*type_p));
+ WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p));
+ }
+ /* FALLTHRU */
+
+ default:
+ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
+ {
+ int i, len;
+
+ /* Walk over all the sub-trees of this operand. */
+ len = TREE_OPERAND_LENGTH (*tp);
+
+ /* Go through the subtrees. We need to do this in forward order so
+ that the scope of a FOR_EXPR is handled properly. */
+ if (len)
+ {
+ for (i = 0; i < len - 1; ++i)
+ WALK_SUBTREE (TREE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1));
+ }
+ }
+ /* If this is a type, walk the needed fields in the type. */
+ else if (TYPE_P (*tp))
+ return walk_type_fields (*tp, func, data, pset, lh);
+ break;
+ }
+
+ /* We didn't find what we were looking for. */
+ return NULL_TREE;
+
+#undef WALK_SUBTREE_TAIL
+}
+#undef WALK_SUBTREE
+
+/* Like walk_tree, but does not walk duplicate nodes more than once. */
+
+tree
+walk_tree_without_duplicates_1 (tree *tp, walk_tree_fn func, void *data,
+ walk_tree_lh lh)
+{
+ tree result;
+ struct pointer_set_t *pset;
+
+ pset = pointer_set_create ();
+ result = walk_tree_1 (tp, func, data, pset, lh);
+ pointer_set_destroy (pset);
+ return result;
+}
+
+
+tree *
+tree_block (tree t)
+{
+ char const c = TREE_CODE_CLASS (TREE_CODE (t));
+
+ if (IS_EXPR_CODE_CLASS (c))
+ return &t->exp.block;
+ gcc_unreachable ();
+ return NULL;
+}
+
+/* Build and return a TREE_LIST of arguments in the CALL_EXPR exp.
+ FIXME: don't use this function. It exists for compatibility with
+ the old representation of CALL_EXPRs where a list was used to hold the
+ arguments. Places that currently extract the arglist from a CALL_EXPR
+ ought to be rewritten to use the CALL_EXPR itself. */
+tree
+call_expr_arglist (tree exp)
+{
+ tree arglist = NULL_TREE;
+ int i;
+ for (i = call_expr_nargs (exp) - 1; i >= 0; i--)
+ arglist = tree_cons (NULL_TREE, CALL_EXPR_ARG (exp, i), arglist);
+ return arglist;
+}
+
+
+/* Create a nameless artificial label and put it in the current function
+ context. Returns the newly created label. */
+
+tree
+create_artificial_label (void)
+{
+ tree lab = build_decl (LABEL_DECL, NULL_TREE, void_type_node);
+
+ DECL_ARTIFICIAL (lab) = 1;
+ DECL_IGNORED_P (lab) = 1;
+ DECL_CONTEXT (lab) = current_function_decl;
+ return lab;
+}
+
+/* Given a tree, try to return a useful variable name that we can use
+ to prefix a temporary that is being assigned the value of the tree.
+ I.E. given <temp> = &A, return A. */
+
+const char *
+get_name (tree t)
+{
+ tree stripped_decl;
+
+ stripped_decl = t;
+ STRIP_NOPS (stripped_decl);
+ if (DECL_P (stripped_decl) && DECL_NAME (stripped_decl))
+ return IDENTIFIER_POINTER (DECL_NAME (stripped_decl));
+ else
+ {
+ switch (TREE_CODE (stripped_decl))
+ {
+ case ADDR_EXPR:
+ return get_name (TREE_OPERAND (stripped_decl, 0));
+ default:
+ return NULL;
+ }
+ }
+}
+
+/* Return true if TYPE has a variable argument list. */
+
+bool
+stdarg_p (tree fntype)
+{
+ function_args_iterator args_iter;
+ tree n = NULL_TREE, t;
+
+ if (!fntype)
+ return false;
+
+ FOREACH_FUNCTION_ARGS(fntype, t, args_iter)
+ {
+ n = t;
+ }
+
+ return n != NULL_TREE && n != void_type_node;
+}
+
+/* Return true if TYPE has a prototype. */
+
+bool
+prototype_p (tree fntype)
+{
+ tree t;
+
+ gcc_assert (fntype != NULL_TREE);
+
+ t = TYPE_ARG_TYPES (fntype);
+ return (t != NULL_TREE);
+}
+
+/* Return the number of arguments that a function has. */
+
+int
+function_args_count (tree fntype)
+{
+ function_args_iterator args_iter;
+ tree t;
+ int num = 0;
+
+ if (fntype)
+ {
+ FOREACH_FUNCTION_ARGS(fntype, t, args_iter)
+ {
+ num++;
+ }
+ }
+
+ return num;
+}
+
+/* If BLOCK is inlined from an __attribute__((__artificial__))
+ routine, return pointer to location from where it has been
+ called. */
+location_t *
+block_nonartificial_location (tree block)
+{
+ location_t *ret = NULL;
+
+ while (block && TREE_CODE (block) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (block))
+ {
+ tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+
+ while (TREE_CODE (ao) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (ao)
+ && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
+ ao = BLOCK_ABSTRACT_ORIGIN (ao);
+
+ if (TREE_CODE (ao) == FUNCTION_DECL)
+ {
+ /* If AO is an artificial inline, point RET to the
+ call site locus at which it has been inlined and continue
+ the loop, in case AO's caller is also an artificial
+ inline. */
+ if (DECL_DECLARED_INLINE_P (ao)
+ && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao)))
+ ret = &BLOCK_SOURCE_LOCATION (block);
+ else
+ break;
+ }
+ else if (TREE_CODE (ao) != BLOCK)
+ break;
+
+ block = BLOCK_SUPERCONTEXT (block);
+ }
+ return ret;
+}
+
+
+/* If EXP is inlined from an __attribute__((__artificial__))
+ function, return the location of the original call expression. */
+
+location_t
+tree_nonartificial_location (tree exp)
+{
+ location_t *loc = block_nonartificial_location (TREE_BLOCK (exp));
+
+ if (loc)
+ return *loc;
+ else
+ return EXPR_LOCATION (exp);
+}
+
+
+/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq
+ nodes. */
+
+/* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */
+
+static hashval_t
+cl_option_hash_hash (const void *x)
+{
+ const_tree const t = (const_tree) x;
+ const char *p;
+ size_t i;
+ size_t len = 0;
+ hashval_t hash = 0;
+
+ if (TREE_CODE (t) == OPTIMIZATION_NODE)
+ {
+ p = (const char *)TREE_OPTIMIZATION (t);
+ len = sizeof (struct cl_optimization);
+ }
+
+ else if (TREE_CODE (t) == TARGET_OPTION_NODE)
+ {
+ p = (const char *)TREE_TARGET_OPTION (t);
+ len = sizeof (struct cl_target_option);
+ }
+
+ else
+ gcc_unreachable ();
+
+ /* assume most opt flags are just 0/1, some are 2-3, and a few might be
+ something else. */
+ for (i = 0; i < len; i++)
+ if (p[i])
+ hash = (hash << 4) ^ ((i << 2) | p[i]);
+
+ return hash;
+}
+
+/* Return nonzero if the value represented by *X (an OPTIMIZATION or
+ TARGET_OPTION tree node) is the same as that given by *Y, which is the
+ same. */
+
+static int
+cl_option_hash_eq (const void *x, const void *y)
+{
+ const_tree const xt = (const_tree) x;
+ const_tree const yt = (const_tree) y;
+ const char *xp;
+ const char *yp;
+ size_t len;
+
+ if (TREE_CODE (xt) != TREE_CODE (yt))
+ return 0;
+
+ if (TREE_CODE (xt) == OPTIMIZATION_NODE)
+ {
+ xp = (const char *)TREE_OPTIMIZATION (xt);
+ yp = (const char *)TREE_OPTIMIZATION (yt);
+ len = sizeof (struct cl_optimization);
+ }
+
+ else if (TREE_CODE (xt) == TARGET_OPTION_NODE)
+ {
+ xp = (const char *)TREE_TARGET_OPTION (xt);
+ yp = (const char *)TREE_TARGET_OPTION (yt);
+ len = sizeof (struct cl_target_option);
+ }
+
+ else
+ gcc_unreachable ();
+
+ return (memcmp (xp, yp, len) == 0);
+}
+
+/* Build an OPTIMIZATION_NODE based on the current options. */
+
+tree
+build_optimization_node (void)
+{
+ tree t;
+ void **slot;
+
+ /* Use the cache of optimization nodes. */
+
+ cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node));
+
+ slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT);
+ t = (tree) *slot;
+ if (!t)
+ {
+ /* Insert this one into the hash table. */
+ t = cl_optimization_node;
+ *slot = t;
+
+ /* Make a new node for next time round. */
+ cl_optimization_node = make_node (OPTIMIZATION_NODE);
+ }
+
+ return t;
+}
+
+/* Build a TARGET_OPTION_NODE based on the current options. */
+
+tree
+build_target_option_node (void)
+{
+ tree t;
+ void **slot;
+
+ /* Use the cache of optimization nodes. */
+
+ cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node));
+
+ slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT);
+ t = (tree) *slot;
+ if (!t)
+ {
+ /* Insert this one into the hash table. */
+ t = cl_target_option_node;
+ *slot = t;
+
+ /* Make a new node for next time round. */
+ cl_target_option_node = make_node (TARGET_OPTION_NODE);
+ }
+
+ return t;
+}
+
+/* Determine the "ultimate origin" of a block. The block may be an inlined
+ instance of an inlined instance of a block which is local to an inline
+ function, so we have to trace all of the way back through the origin chain
+ to find out what sort of node actually served as the original seed for the
+ given block. */
+
+tree
+block_ultimate_origin (const_tree block)
+{
+ tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
+
+ /* output_inline_function sets BLOCK_ABSTRACT_ORIGIN for all the
+ nodes in the function to point to themselves; ignore that if
+ we're trying to output the abstract instance of this function. */
+ if (BLOCK_ABSTRACT (block) && immediate_origin == block)
+ return NULL_TREE;
+
+ if (immediate_origin == NULL_TREE)
+ return NULL_TREE;
+ else
+ {
+ tree ret_val;
+ tree lookahead = immediate_origin;
+
+ do
+ {
+ ret_val = lookahead;
+ lookahead = (TREE_CODE (ret_val) == BLOCK
+ ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL);
+ }
+ while (lookahead != NULL && lookahead != ret_val);
+
+ /* The block's abstract origin chain may not be the *ultimate* origin of
+ the block. It could lead to a DECL that has an abstract origin set.
+ If so, we want that DECL's abstract origin (which is what DECL_ORIGIN
+ will give us if it has one). Note that DECL's abstract origins are
+ supposed to be the most distant ancestor (or so decl_ultimate_origin
+ claims), so we don't need to loop following the DECL origins. */
+ if (DECL_P (ret_val))
+ return DECL_ORIGIN (ret_val);
+
+ return ret_val;
+ }
+}
+
+#include "gt-tree.h"