X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Ftree.c;h=448d329d3c88c441614c17535a8da38411a5dbf4;hp=76f52cdcb6dc734e77f797e818c57761f82cc00e;hb=3f99be76a141c6ce193375340a6dc1284e19e189;hpb=3284a24216e1b356c4b7dcc496cf16850e858a4a diff --git a/gcc/tree.c b/gcc/tree.c index 76f52cdcb6d..448d329d3c8 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -93,6 +93,7 @@ static const char * const tree_node_kind_names[] = { "binfos", "phi_nodes", "ssa names", + "constructors", "random kinds", "lang_decl kinds", "lang_type kinds" @@ -133,12 +134,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) /* General tree->tree mapping structure for use in hash tables. */ -struct tree_map GTY(()) -{ - hashval_t hash; - tree from; - tree to; -}; static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t debug_expr_for_decl; @@ -146,11 +141,20 @@ static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t value_expr_for_decl; +static GTY ((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map))) + htab_t init_priority_for_decl; + +struct tree_int_map GTY(()) +{ + tree from; + unsigned short to; +}; +static unsigned int tree_int_map_hash (const void *); +static int tree_int_map_eq (const void *, const void *); +static int tree_int_map_marked_p (const void *); 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 int tree_map_eq (const void *, const void *); -static hashval_t tree_map_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); @@ -158,19 +162,20 @@ static void print_debug_expr_statistics (void); static void print_value_expr_statistics (void); static tree make_vector_type (tree, int, enum machine_mode); static int type_hash_marked_p (const void *); -static int tree_map_marked_p (const void *); static unsigned int type_hash_list (tree, hashval_t); static unsigned int attribute_hash_list (tree, hashval_t); tree global_trees[TI_MAX]; tree integer_types[itk_none]; +unsigned char tree_contains_struct[256][64]; /* Init tree.c. */ void 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); @@ -180,12 +185,62 @@ init_ttree (void) value_expr_for_decl = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0); + init_priority_for_decl = htab_create_ggc (512, tree_int_map_hash, + tree_int_map_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); + tree_contains_struct[FUNCTION_DECL][TS_DECL_NON_COMMON] = 1; + tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_NON_COMMON] = 1; + tree_contains_struct[TYPE_DECL][TS_DECL_NON_COMMON] = 1; + + + tree_contains_struct[CONST_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[VAR_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[PARM_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[RESULT_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[FUNCTION_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[TYPE_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[LABEL_DECL][TS_DECL_COMMON] = 1; + tree_contains_struct[FIELD_DECL][TS_DECL_COMMON] = 1; + + + tree_contains_struct[CONST_DECL][TS_DECL_WRTL] = 1; + tree_contains_struct[VAR_DECL][TS_DECL_WRTL] = 1; + tree_contains_struct[PARM_DECL][TS_DECL_WRTL] = 1; + tree_contains_struct[RESULT_DECL][TS_DECL_WRTL] = 1; + tree_contains_struct[FUNCTION_DECL][TS_DECL_WRTL] = 1; + tree_contains_struct[LABEL_DECL][TS_DECL_WRTL] = 1; + + tree_contains_struct[CONST_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[VAR_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[PARM_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[RESULT_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[FUNCTION_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[TYPE_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[LABEL_DECL][TS_DECL_MINIMAL] = 1; + tree_contains_struct[FIELD_DECL][TS_DECL_MINIMAL] = 1; + + tree_contains_struct[VAR_DECL][TS_DECL_WITH_VIS] = 1; + tree_contains_struct[FUNCTION_DECL][TS_DECL_WITH_VIS] = 1; + tree_contains_struct[TYPE_DECL][TS_DECL_WITH_VIS] = 1; + tree_contains_struct[TRANSLATION_UNIT_DECL][TS_DECL_WITH_VIS] = 1; + + tree_contains_struct[VAR_DECL][TS_VAR_DECL] = 1; + tree_contains_struct[FIELD_DECL][TS_FIELD_DECL] = 1; + tree_contains_struct[PARM_DECL][TS_PARM_DECL] = 1; + tree_contains_struct[LABEL_DECL][TS_LABEL_DECL] = 1; + tree_contains_struct[RESULT_DECL][TS_RESULT_DECL] = 1; + tree_contains_struct[CONST_DECL][TS_CONST_DECL] = 1; + tree_contains_struct[TYPE_DECL][TS_TYPE_DECL] = 1; + tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL] = 1; + + lang_hooks.init_ts (); } @@ -197,7 +252,7 @@ decl_assembler_name (tree decl) { if (!DECL_ASSEMBLER_NAME_SET_P (decl)) lang_hooks.set_decl_assembler_name (decl); - return DECL_CHECK (decl)->decl.assembler_name; + return DECL_WITH_VIS_CHECK (decl)->decl_with_vis.assembler_name; } /* Compute the number of bytes occupied by a tree with code CODE. @@ -209,7 +264,29 @@ tree_code_size (enum tree_code code) switch (TREE_CODE_CLASS (code)) { case tcc_declaration: /* A decl node */ - return sizeof (struct tree_decl); + { + switch (code) + { + case FIELD_DECL: + return sizeof (struct tree_field_decl); + case PARM_DECL: + return sizeof (struct tree_parm_decl); + case VAR_DECL: + return sizeof (struct tree_var_decl); + case LABEL_DECL: + return sizeof (struct tree_label_decl); + case RESULT_DECL: + return sizeof (struct tree_result_decl); + case CONST_DECL: + return sizeof (struct tree_const_decl); + case TYPE_DECL: + return sizeof (struct tree_type_decl); + case FUNCTION_DECL: + return sizeof (struct tree_function_decl); + default: + return sizeof (struct tree_decl_non_common); + } + } case tcc_type: /* a type node */ return sizeof (struct tree_type); @@ -252,6 +329,7 @@ tree_code_size (enum tree_code code) case STATEMENT_LIST: return sizeof (struct tree_statement_list); case BLOCK: return sizeof (struct tree_block); case VALUE_HANDLE: return sizeof (struct tree_value_handle); + case CONSTRUCTOR: return sizeof (struct tree_constructor); default: return lang_hooks.tree_size (code); @@ -342,7 +420,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = id_kind; break; - case TREE_VEC:; + case TREE_VEC: kind = vec_kind; break; @@ -362,6 +440,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) kind = b_kind; break; + case CONSTRUCTOR: + kind = constr_kind; + break; + default: kind = x_kind; break; @@ -395,17 +477,18 @@ make_node_stat (enum tree_code code MEM_STAT_DECL) if (code != FUNCTION_DECL) DECL_ALIGN (t) = 1; DECL_USER_ALIGN (t) = 0; - DECL_IN_SYSTEM_HEADER (t) = in_system_header; + if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) + DECL_IN_SYSTEM_HEADER (t) = in_system_header; + /* We have not yet computed the alias set for this declaration. */ + DECL_POINTER_ALIAS_SET (t) = -1; DECL_SOURCE_LOCATION (t) = input_location; DECL_UID (t) = next_decl_uid++; - /* We have not yet computed the alias set for this declaration. */ - DECL_POINTER_ALIAS_SET (t) = -1; break; case tcc_type: TYPE_UID (t) = next_type_uid++; - TYPE_ALIGN (t) = char_type_node ? TYPE_ALIGN (char_type_node) : 0; + TYPE_ALIGN (t) = BITS_PER_UNIT; TYPE_USER_ALIGN (t) = 0; TYPE_MAIN_VARIANT (t) = t; @@ -480,6 +563,11 @@ copy_node_stat (tree node MEM_STAT_DECL) SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node)); DECL_HAS_VALUE_EXPR_P (t) = 1; } + if (TREE_CODE (node) == VAR_DECL && DECL_HAS_INIT_PRIORITY_P (node)) + { + SET_DECL_INIT_PRIORITY (t, DECL_INIT_PRIORITY (node)); + DECL_HAS_INIT_PRIORITY_P (t) = 1; + } } else if (TREE_CODE_CLASS (code) == tcc_type) @@ -795,7 +883,7 @@ cst_and_fits_in_hwi (tree x) } /* Return a new VECTOR_CST node whose type is TYPE and whose values - are in a list pointed by VALS. */ + are in a list pointed to by VALS. */ tree build_vector (tree type, tree vals) @@ -822,27 +910,72 @@ build_vector (tree type, tree vals) return v; } +/* Return a new VECTOR_CST node whose type is TYPE and whose values + are extracted from V, a vector of CONSTRUCTOR_ELT. */ + +tree +build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v) +{ + tree list = NULL_TREE; + unsigned HOST_WIDE_INT idx; + tree value; + + FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value) + list = tree_cons (NULL_TREE, value, list); + return build_vector (type, nreverse (list)); +} + /* Return a new CONSTRUCTOR node whose type is TYPE and whose values - are in a list pointed to by VALS. */ + are in the VEC pointed to by VALS. */ tree -build_constructor (tree type, tree vals) +build_constructor (tree type, VEC(constructor_elt,gc) *vals) { tree c = make_node (CONSTRUCTOR); TREE_TYPE (c) = type; CONSTRUCTOR_ELTS (c) = vals; + return c; +} + +/* Build a CONSTRUCTOR node made of a single initializer, with the specified + INDEX and VALUE. */ +tree +build_constructor_single (tree type, tree index, tree value) +{ + VEC(constructor_elt,gc) *v; + constructor_elt *elt; + + v = VEC_alloc (constructor_elt, gc, 1); + elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = index; + elt->value = value; + + return build_constructor (type, v); +} + + +/* Return a new CONSTRUCTOR node whose type is TYPE and whose values + are in a list pointed to by VALS. */ +tree +build_constructor_from_list (tree type, tree vals) +{ + tree t; + VEC(constructor_elt,gc) *v = NULL; - /* ??? May not be necessary. Mirrors what build does. */ if (vals) { - TREE_SIDE_EFFECTS (c) = TREE_SIDE_EFFECTS (vals); - TREE_READONLY (c) = TREE_READONLY (vals); - TREE_CONSTANT (c) = TREE_CONSTANT (vals); - TREE_INVARIANT (c) = TREE_INVARIANT (vals); + v = VEC_alloc (constructor_elt, gc, list_length (vals)); + for (t = vals; t; t = TREE_CHAIN (t)) + { + constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = TREE_PURPOSE (t); + elt->value = TREE_VALUE (t); + } } - return c; + return build_constructor (type, v); } + /* Return a new REAL_CST node whose type is TYPE and value is D. */ tree @@ -920,6 +1053,8 @@ build_string (int len, const char *str) memset (s, 0, sizeof (struct tree_common)); TREE_SET_CODE (s, STRING_CST); + TREE_CONSTANT (s) = 1; + TREE_INVARIANT (s) = 1; TREE_STRING_LENGTH (s) = len; memcpy ((char *) TREE_STRING_POINTER (s), str, len); ((char *) TREE_STRING_POINTER (s))[len] = '\0'; @@ -1814,9 +1949,31 @@ tree_node_structure (tree t) enum tree_code code = TREE_CODE (t); switch (TREE_CODE_CLASS (code)) - { + { case tcc_declaration: - return TS_DECL; + { + switch (code) + { + case FIELD_DECL: + return TS_FIELD_DECL; + case PARM_DECL: + return TS_PARM_DECL; + case VAR_DECL: + return TS_VAR_DECL; + case LABEL_DECL: + return TS_LABEL_DECL; + case RESULT_DECL: + return TS_RESULT_DECL; + case CONST_DECL: + return TS_CONST_DECL; + case TYPE_DECL: + return TS_TYPE_DECL; + case FUNCTION_DECL: + return TS_FUNCTION_DECL; + default: + return TS_DECL_NON_COMMON; + } + } case tcc_type: return TS_TYPE; case tcc_reference: @@ -1847,6 +2004,7 @@ tree_node_structure (tree t) case PLACEHOLDER_EXPR: return TS_COMMON; case STATEMENT_LIST: return TS_STATEMENT_LIST; case BLOCK: return TS_BLOCK; + case CONSTRUCTOR: return TS_CONSTRUCTOR; case TREE_BINFO: return TS_BINFO; case VALUE_HANDLE: return TS_VALUE_HANDLE; @@ -1900,6 +2058,9 @@ contains_placeholder_p (tree exp) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)) || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2))); + case CALL_EXPR: + return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)); + default: break; } @@ -2466,6 +2627,8 @@ do { tree _node = (NODE); \ UPDATE_TITCSE (TREE_OPERAND (node, 2)); } + node = lang_hooks.expr_to_decl (node, &tc, &ti, &se); + /* Now see what's inside. If it's an INDIRECT_REF, copy our properties from 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 @@ -2875,10 +3038,13 @@ build_decl_stat (enum tree_code code, tree name, tree type MEM_STAT_DECL) else if (code == FUNCTION_DECL) DECL_MODE (t) = FUNCTION_MODE; - /* Set default visibility to whatever the user supplied with - visibility_specified depending on #pragma GCC visibility. */ - DECL_VISIBILITY (t) = default_visibility; - DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma; + if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) + { + /* Set default visibility to whatever the user supplied with + visibility_specified depending on #pragma GCC visibility. */ + DECL_VISIBILITY (t) = default_visibility; + DECL_VISIBILITY_SPECIFIED (t) = visibility_options.inpragma; + } return t; } @@ -3511,7 +3677,7 @@ build_variant_type_copy (tree type) /* Return true if the from tree in both tree maps are equal. */ -static int +int tree_map_eq (const void *va, const void *vb) { const struct tree_map *a = va, *b = vb; @@ -3520,7 +3686,7 @@ tree_map_eq (const void *va, const void *vb) /* Hash a from tree in a tree_map. */ -static hashval_t +unsigned int tree_map_hash (const void *item) { return (((const struct tree_map *) item)->hash); @@ -3530,7 +3696,7 @@ tree_map_hash (const void *item) purposes. We simply return true if the from tree is marked, so that this structure goes away when the from tree goes away. */ -static int +int tree_map_marked_p (const void *p) { tree from = ((struct tree_map *) p)->from; @@ -3538,6 +3704,65 @@ tree_map_marked_p (const void *p) return ggc_marked_p (from); } +/* Return true if the trees in the tree_int_map *'s VA and VB are equal. */ + +static int +tree_int_map_eq (const void *va, const void *vb) +{ + const struct tree_int_map *a = va, *b = vb; + return (a->from == b->from); +} + +/* Hash a from tree in the tree_int_map * ITEM. */ + +static unsigned int +tree_int_map_hash (const void *item) +{ + return htab_hash_pointer (((const struct tree_int_map *)item)->from); +} + +/* Return true if this tree int map structure is marked for garbage collection + purposes. We simply return true if the from tree_int_map *P's from tree is marked, so that this + structure goes away when the from tree goes away. */ + +static int +tree_int_map_marked_p (const void *p) +{ + tree from = ((struct tree_int_map *) p)->from; + + return ggc_marked_p (from); +} +/* Lookup an init priority for FROM, and return it if we find one. */ + +unsigned short +decl_init_priority_lookup (tree from) +{ + struct tree_int_map *h, in; + in.from = from; + + h = htab_find_with_hash (init_priority_for_decl, + &in, htab_hash_pointer (from)); + if (h) + return h->to; + return 0; +} + +/* Insert a mapping FROM->TO in the init priority hashtable. */ + +void +decl_init_priority_insert (tree from, unsigned short to) +{ + struct tree_int_map *h; + void **loc; + + h = ggc_alloc (sizeof (struct tree_int_map)); + h->from = from; + h->to = to; + loc = htab_find_slot_with_hash (init_priority_for_decl, h, + htab_hash_pointer (from), INSERT); + *(struct tree_int_map **) loc = h; +} + /* Print out the statistics for the DECL_DEBUG_EXPR hash table. */ static void @@ -4022,7 +4247,7 @@ tree_int_cst_compare (tree t1, tree t2) /* Return 1 if T is an INTEGER_CST that can be manipulated efficiently on the host. If POS is zero, the value can be represented in a single - HOST_WIDE_INT. If POS is nonzero, the value must be positive and can + HOST_WIDE_INT. If POS is nonzero, the value must be non-negative and can be represented in a single unsigned HOST_WIDE_INT. */ int @@ -4040,7 +4265,7 @@ host_integerp (tree t, int pos) /* Return the HOST_WIDE_INT least significant bits of T if it is an INTEGER_CST and there is no overflow. POS is nonzero if the result must - be positive. We must be able to satisfy the above conditions. */ + be non-negative. We must be able to satisfy the above conditions. */ HOST_WIDE_INT tree_low_cst (tree t, int pos) @@ -4153,8 +4378,21 @@ simple_cst_equal (tree t1, tree t2) TREE_STRING_LENGTH (t1))); case CONSTRUCTOR: - return simple_cst_list_equal (CONSTRUCTOR_ELTS (t1), - CONSTRUCTOR_ELTS (t2)); + { + unsigned HOST_WIDE_INT idx; + VEC(constructor_elt, gc) *v1 = CONSTRUCTOR_ELTS (t1); + VEC(constructor_elt, gc) *v2 = CONSTRUCTOR_ELTS (t2); + + if (VEC_length (constructor_elt, v1) != VEC_length (constructor_elt, v2)) + return false; + + for (idx = 0; idx < VEC_length (constructor_elt, v1); ++idx) + /* ??? Should we handle also fields here? */ + if (!simple_cst_equal (VEC_index (constructor_elt, v1, idx)->value, + VEC_index (constructor_elt, v2, idx)->value)) + return false; + return true; + } case SAVE_EXPR: return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); @@ -4362,6 +4600,17 @@ iterative_hash_expr (tree t, hashval_t val) for (; t; t = TREE_CHAIN (t)) val = iterative_hash_expr (TREE_VALUE (t), val); return val; + case CONSTRUCTOR: + { + unsigned HOST_WIDE_INT idx; + tree field, value; + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value) + { + val = iterative_hash_expr (field, val); + val = iterative_hash_expr (value, val); + } + return val; + } case FUNCTION_DECL: /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form. Otherwise nodes that compare equal @@ -4440,6 +4689,9 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, { tree t; + if (to_type == error_mark_node) + return error_mark_node; + /* In some cases, languages will have things that aren't a POINTER_TYPE (such as a RECORD_TYPE for fat pointers in Ada) as TYPE_POINTER_TO. In that case, return that type without regard to the rest of our @@ -5662,6 +5914,31 @@ tree_class_check_failed (const tree node, const enum tree_code_class cl, TREE_CODE_CLASS_STRING (TREE_CODE_CLASS (TREE_CODE (node))), tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); } +#undef DEFTREESTRUCT +#define DEFTREESTRUCT(VAL, NAME) NAME, + +static const char *ts_enum_names[] = { +#include "treestruct.def" +}; +#undef DEFTREESTRUCT + +#define TS_ENUM_NAME(EN) (ts_enum_names[(EN)]) + +/* Similar to tree_class_check_failed, except that we check for + whether CODE contains the tree structure identified by EN. */ + +void +tree_contains_struct_check_failed (const tree node, + const enum tree_node_structure_enum en, + const char *file, int line, + const char *function) +{ + internal_error + ("tree check: expected tree that contains %qs structure, have %qs in %s, at %s:%d", + TS_ENUM_NAME(en), + tree_code_name[TREE_CODE (node)], function, trim_filename (file), line); +} + /* Similar to above, except that the check is for the bounds of a TREE_VEC's (dynamically sized) vector. */ @@ -6209,14 +6486,14 @@ initializer_zerop (tree init) return true; case CONSTRUCTOR: - elt = CONSTRUCTOR_ELTS (init); - if (elt == NULL_TREE) - return true; + { + unsigned HOST_WIDE_INT idx; - for (; elt ; elt = TREE_CHAIN (elt)) - if (! initializer_zerop (TREE_VALUE (elt))) - return false; - return true; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt) + if (!initializer_zerop (elt)) + return false; + return true; + } default: return false; @@ -6415,43 +6692,64 @@ tree upper_bound_in_type (tree outer, tree inner) { unsigned HOST_WIDE_INT lo, hi; - unsigned bits = TYPE_PRECISION (inner); + 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 (); + } - if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner)) + /* Compute 2^^prec - 1. */ + if (prec <= HOST_BITS_PER_WIDE_INT) { - /* 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; - } + hi = 0; + lo = ((~(unsigned HOST_WIDE_INT) 0) + >> (HOST_BITS_PER_WIDE_INT - prec)); } 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; - } + hi = ((~(unsigned HOST_WIDE_INT) 0) + >> (2 * HOST_BITS_PER_WIDE_INT - prec)); + lo = ~(unsigned HOST_WIDE_INT) 0; } - return fold_convert (outer, - build_int_cst_wide (inner, lo, hi)); + return build_int_cst_wide (outer, lo, hi); } /* Returns the smallest value obtainable by casting something in INNER type to @@ -6461,23 +6759,39 @@ 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)) + 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 (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; + /* 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 fold_convert (outer, - build_int_cst_wide (inner, lo, hi)); + return build_int_cst_wide (outer, lo, hi); } /* Return nonzero if two operands that are suitable for PHI nodes are @@ -6827,7 +7141,16 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, struct pointer_set_t *pset) WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); case CONSTRUCTOR: - WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp)); + { + 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));