This is a summary report of a (failed) attempt to address memory and compile-time usage of large (static array) initializers. The problem is that we both use TREEs to do array indices arithmetic in c-typeck.c:process_init_element and that we pin down memory for INTEGER_CST tree nodes in both the large integer hashtable and the CONSTRUCTOR elements.
The following patch tries to address this by - using HOST_WIDE_INTs for the index arithmetic - storing only the first index of a consecutive sequence of initializers, the rest will have NULL_TREEs Apart from some unresolved failures (gnu99 initializers, store-ccp) this works, but really CONSTRUCTOR users don't cope with NULL_TREE indices. A real solution would ditch TREE indices in favor of HOST_WIDE_INT ones, but this won't work with RANGEs or FIELD_DECLs (though for the latter we could store the decl offset, and I believe we could handle the fallout for C and C++, dunno about possible initializers at non-constant offsets in other languages). With the patch memory usage for PR12245 is down to 160MB (from 250MB). For a reduced testcase it is 160MB -> 80MB and 16s to 7s reduced compile time. Any ideas on how to proceed? Can we figure out (at output_init_element time), if the array initializer is a static one? Thanks for any input, Richard. Index: c-typeck.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v retrieving revision 1.480 diff -c -3 -p -r1.480 c-typeck.c *** c-typeck.c 2 Oct 2005 19:15:58 -0000 1.480 --- c-typeck.c 3 Oct 2005 17:34:06 -0000 *************** static char *print_spelling (char *); *** 94,99 **** --- 94,100 ---- static void warning_init (const char *); static tree digest_init (tree, tree, bool, int); static void output_init_element (tree, bool, tree, tree, int); + static void output_array_init_element (tree, bool, tree, HOST_WIDE_INT, int); static void output_pending_init_elements (int); static int set_designator (int); static void push_range_stack (tree); *************** static tree constructor_fields; *** 4682,4687 **** --- 4683,4689 ---- /* For an ARRAY_TYPE, this is the specified index at which to store the next element we get. */ static tree constructor_index; + static HOST_WIDE_INT aconstructor_index; /* For an ARRAY_TYPE, this is the maximum index. */ static tree constructor_max_index; *************** static tree constructor_unfilled_fields; *** 4692,4697 **** --- 4694,4700 ---- /* For an ARRAY_TYPE, this is the index of the first element not yet written out. */ static tree constructor_unfilled_index; + static HOST_WIDE_INT aconstructor_unfilled_index; /* In a RECORD_TYPE, the byte index of the next consecutive field. This is so we can generate gaps between fields, when appropriate. */ *************** really_start_incremental_init (tree type *** 4999,5015 **** && TREE_CODE (constructor_max_index) != INTEGER_CST) constructor_max_index = build_int_cst (NULL_TREE, -1); ! constructor_index ! = convert (bitsizetype, ! TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); } else { ! constructor_index = bitsize_zero_node; constructor_max_index = NULL_TREE; } ! constructor_unfilled_index = constructor_index; } else if (TREE_CODE (constructor_type) == VECTOR_TYPE) { --- 5002,5017 ---- && TREE_CODE (constructor_max_index) != INTEGER_CST) constructor_max_index = build_int_cst (NULL_TREE, -1); ! aconstructor_index = TREE_INT_CST_LOW ( ! TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); } else { ! aconstructor_index = 0; constructor_max_index = NULL_TREE; } ! aconstructor_unfilled_index = aconstructor_index; } else if (TREE_CODE (constructor_type) == VECTOR_TYPE) { *************** push_init_level (int implicit) *** 5054,5061 **** process_init_element (pop_init_level (1)); else if (TREE_CODE (constructor_type) == ARRAY_TYPE && constructor_max_index ! && tree_int_cst_lt (constructor_max_index, ! constructor_index)) process_init_element (pop_init_level (1)); else break; --- 5056,5063 ---- process_init_element (pop_init_level (1)); else if (TREE_CODE (constructor_type) == ARRAY_TYPE && constructor_max_index ! && compare_tree_int (constructor_max_index, ! aconstructor_index) == -1) process_init_element (pop_init_level (1)); else break; *************** push_init_level (int implicit) *** 5071,5077 **** && constructor_fields) value = find_init_member (constructor_fields); else if (TREE_CODE (constructor_type) == ARRAY_TYPE) ! value = find_init_member (constructor_index); } p = XNEW (struct constructor_stack); --- 5073,5086 ---- && constructor_fields) value = find_init_member (constructor_fields); else if (TREE_CODE (constructor_type) == ARRAY_TYPE) ! value = find_init_member (build_int_cst (bitsizetype, aconstructor_index)); ! } ! ! if (TREE_CODE (constructor_type) == ARRAY_TYPE) ! { ! constructor_index = build_int_cst (bitsizetype, aconstructor_index); ! constructor_unfilled_index = build_int_cst (bitsizetype, ! aconstructor_unfilled_index); } p = XNEW (struct constructor_stack); *************** push_init_level (int implicit) *** 5133,5139 **** else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { constructor_type = TREE_TYPE (constructor_type); ! push_array_bounds (tree_low_cst (constructor_index, 0)); constructor_depth++; } --- 5142,5148 ---- else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { constructor_type = TREE_TYPE (constructor_type); ! push_array_bounds (aconstructor_index); constructor_depth++; } *************** push_init_level (int implicit) *** 5201,5214 **** && TREE_CODE (constructor_max_index) != INTEGER_CST) constructor_max_index = build_int_cst (NULL_TREE, -1); ! constructor_index ! = convert (bitsizetype, TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); } else ! constructor_index = bitsize_zero_node; ! constructor_unfilled_index = constructor_index; if (value && TREE_CODE (value) == STRING_CST) { /* We need to split the char/wchar array into individual --- 5210,5222 ---- && TREE_CODE (constructor_max_index) != INTEGER_CST) constructor_max_index = build_int_cst (NULL_TREE, -1); ! aconstructor_index = TREE_INT_CST_LOW ( TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); } else ! aconstructor_index = 0; ! aconstructor_unfilled_index = aconstructor_index; if (value && TREE_CODE (value) == STRING_CST) { /* We need to split the char/wchar array into individual *************** push_init_level (int implicit) *** 5216,5221 **** --- 5224,5231 ---- everywhere. */ set_nonincremental_init_from_string (value); } + constructor_index = NULL; + constructor_unfilled_index = NULL; } else { *************** pop_init_level (int implicit) *** 5270,5276 **** { /* Silently discard empty initializations. The parser will already have pedwarned for empty brackets. */ ! if (integer_zerop (constructor_unfilled_index)) constructor_type = NULL_TREE; else { --- 5280,5286 ---- { /* Silently discard empty initializations. The parser will already have pedwarned for empty brackets. */ ! if (aconstructor_unfilled_index == 0) constructor_type = NULL_TREE; else { *************** pop_init_level (int implicit) *** 5376,5381 **** --- 5386,5401 ---- constructor_stack = p->next; free (p); + if (constructor_type + && TREE_CODE (constructor_type) == ARRAY_TYPE + && constructor_index && constructor_unfilled_index) + { + aconstructor_index = TREE_INT_CST_LOW (constructor_index); + aconstructor_unfilled_index = TREE_INT_CST_LOW (constructor_unfilled_index); + constructor_index = NULL; + constructor_unfilled_index = NULL; + } + if (ret.value == 0) { if (constructor_stack == 0) *************** set_init_index (tree first, tree last) *** 5506,5511 **** --- 5526,5532 ---- else { constructor_index = convert (bitsizetype, first); + aconstructor_index = TREE_INT_CST_LOW (first); if (last) { *************** static void *** 5796,5809 **** set_nonincremental_init (void) { unsigned HOST_WIDE_INT ix; ! tree index, value; if (TREE_CODE (constructor_type) != RECORD_TYPE && TREE_CODE (constructor_type) != ARRAY_TYPE) return; FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value) ! add_pending_init (index, value); constructor_elements = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE) { --- 5817,5841 ---- set_nonincremental_init (void) { unsigned HOST_WIDE_INT ix; ! tree index, value, last_index = NULL_TREE; if (TREE_CODE (constructor_type) != RECORD_TYPE && TREE_CODE (constructor_type) != ARRAY_TYPE) return; FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value) ! { ! if (!index) ! { ! if (!last_index) ! index = integer_zero_node; ! else ! index = int_const_binop (PLUS_EXPR, last_index, ! integer_one_node, 0); ! } ! last_index = index; ! add_pending_init (index, value); ! } constructor_elements = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE) { *************** set_nonincremental_init (void) *** 5818,5828 **** else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { if (TYPE_DOMAIN (constructor_type)) ! constructor_unfilled_index ! = convert (bitsizetype, TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); else ! constructor_unfilled_index = bitsize_zero_node; } constructor_incremental = 0; } --- 5850,5861 ---- else if (TREE_CODE (constructor_type) == ARRAY_TYPE) { if (TYPE_DOMAIN (constructor_type)) ! aconstructor_unfilled_index ! = TREE_INT_CST_LOW ( TYPE_MIN_VALUE (TYPE_DOMAIN (constructor_type))); else ! aconstructor_unfilled_index = 0; ! constructor_unfilled_index = NULL; } constructor_incremental = 0; } *************** find_init_member (tree field) *** 5918,5924 **** if (TREE_CODE (constructor_type) == ARRAY_TYPE) { if (constructor_incremental ! && tree_int_cst_lt (field, constructor_unfilled_index)) set_nonincremental_init (); p = constructor_pending_elts; --- 5951,5957 ---- if (TREE_CODE (constructor_type) == ARRAY_TYPE) { if (constructor_incremental ! && compare_tree_int (field, aconstructor_unfilled_index) == -1) set_nonincremental_init (); p = constructor_pending_elts; *************** output_init_element (tree value, bool st *** 6035,6042 **** && (TREE_TYPE (field) == error_mark_node || (COMPLETE_TYPE_P (TREE_TYPE (field)) && integer_zerop (TYPE_SIZE (TREE_TYPE (field))) ! && (TREE_CODE (constructor_type) == ARRAY_TYPE ! || TREE_CHAIN (field))))) return; value = digest_init (type, value, strict_string, require_constant_value); --- 6068,6074 ---- && (TREE_TYPE (field) == error_mark_node || (COMPLETE_TYPE_P (TREE_TYPE (field)) && integer_zerop (TYPE_SIZE (TREE_TYPE (field))) ! && TREE_CHAIN (field)))) return; value = digest_init (type, value, strict_string, require_constant_value); *************** output_init_element (tree value, bool st *** 6048,6067 **** /* If this element doesn't come next in sequence, put it on constructor_pending_elts. */ ! if (TREE_CODE (constructor_type) == ARRAY_TYPE && (!constructor_incremental ! || !tree_int_cst_equal (field, constructor_unfilled_index))) ! { ! if (constructor_incremental ! && tree_int_cst_lt (field, constructor_unfilled_index)) ! set_nonincremental_init (); ! ! add_pending_init (field, value); ! return; ! } ! else if (TREE_CODE (constructor_type) == RECORD_TYPE ! && (!constructor_incremental ! || field != constructor_unfilled_fields)) { /* We do this for records but not for unions. In a union, no matter which field is specified, it can be initialized --- 6080,6088 ---- /* If this element doesn't come next in sequence, put it on constructor_pending_elts. */ ! if (TREE_CODE (constructor_type) == RECORD_TYPE && (!constructor_incremental ! || field != constructor_unfilled_fields)) { /* We do this for records but not for unions. In a union, no matter which field is specified, it can be initialized *************** output_init_element (tree value, bool st *** 6104,6114 **** celt->value = value; /* Advance the variable that indicates sequential elements output. */ ! if (TREE_CODE (constructor_type) == ARRAY_TYPE) ! constructor_unfilled_index ! = size_binop (PLUS_EXPR, constructor_unfilled_index, ! bitsize_one_node); ! else if (TREE_CODE (constructor_type) == RECORD_TYPE) { constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); --- 6125,6131 ---- celt->value = value; /* Advance the variable that indicates sequential elements output. */ ! if (TREE_CODE (constructor_type) == RECORD_TYPE) { constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields); *************** output_init_element (tree value, bool st *** 6128,6133 **** --- 6145,6265 ---- output_pending_init_elements (0); } + /* "Output" the next array constructor element. + At top level, really output it to assembler code now. + Otherwise, collect it in a list from which we will make a CONSTRUCTOR. + TYPE is the data type that the containing data type wants here. + FIELD is the field (a FIELD_DECL) or the index that this element fills. + If VALUE is a string constant, STRICT_STRING is true if it is + unparenthesized or we should not warn here for it being parenthesized. + For other types of VALUE, STRICT_STRING is not used. + + PENDING if non-nil means output pending elements that belong + right after this element. (PENDING is normally 1; + it is 0 while outputting pending elements, to avoid recursion.) */ + + static void + output_array_init_element (tree value, bool strict_string, tree type, + HOST_WIDE_INT field, int pending) + { + constructor_elt *celt; + + if (type == error_mark_node || value == error_mark_node) + { + constructor_erroneous = 1; + return; + } + if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE + && (TREE_CODE (value) == STRING_CST + || TREE_CODE (value) == COMPOUND_LITERAL_EXPR) + && !(TREE_CODE (value) == STRING_CST + && TREE_CODE (type) == ARRAY_TYPE + && INTEGRAL_TYPE_P (TREE_TYPE (type))) + && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)), + TYPE_MAIN_VARIANT (type))) + value = array_to_pointer_conversion (value); + + if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR + && require_constant_value && !flag_isoc99 && pending) + { + /* As an extension, allow initializing objects with static storage + duration with compound literals (which are then treated just as + the brace enclosed list they contain). */ + tree decl = COMPOUND_LITERAL_EXPR_DECL (value); + value = DECL_INITIAL (decl); + } + + if (value == error_mark_node) + constructor_erroneous = 1; + else if (!TREE_CONSTANT (value)) + constructor_constant = 0; + else if (!initializer_constant_valid_p (value, TREE_TYPE (value))) + constructor_simple = 0; + + if (!initializer_constant_valid_p (value, TREE_TYPE (value))) + { + if (require_constant_value) + { + error_init ("initializer element is not constant"); + value = error_mark_node; + } + else if (require_constant_elements) + pedwarn ("initializer element is not computable at load time"); + } + + /* If this field is empty (and not at the end of structure), + don't do anything other than checking the initializer. */ + if (field == -1) + return; + + value = digest_init (type, value, strict_string, require_constant_value); + if (value == error_mark_node) + { + constructor_erroneous = 1; + return; + } + + /* If this element doesn't come next in sequence, + put it on constructor_pending_elts. */ + if (!constructor_incremental + || field != aconstructor_unfilled_index) + { + if (constructor_incremental + && field < aconstructor_unfilled_index) + set_nonincremental_init (); + + add_pending_init (build_int_cst (bitsizetype, field), value); + return; + } + + /* Otherwise, output this element either to + constructor_elements or to the assembler file. */ + + celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL); + /* For consecutive initializers save pinning down an INTEGER_CST node. */ + celt->index = NULL; + if (!VEC_empty (constructor_elt, constructor_elements)) + { + constructor_elt *ocelt; + ocelt = VEC_last (constructor_elt, constructor_elements); + if ((!pending && !ocelt->index) + || (ocelt->index + && (!host_integerp (ocelt->index, 0) + || TREE_INT_CST_LOW (ocelt->index)+1 != (unsigned HOST_WIDE_INT)field))) + celt->index = build_int_cst (bitsizetype, field); + } + else if (!pending) + celt->index = build_int_cst (bitsizetype, field); + celt->value = value; + + /* Advance the variable that indicates sequential elements output. */ + ++aconstructor_unfilled_index; + + /* Now output any pending elements which have become next. */ + if (pending) + output_pending_init_elements (0); + } + /* Output any pending elements which have become next. As we output elements, constructor_unfilled_{fields,index} advances, which may cause other elements to become next; *************** output_pending_init_elements (int all) *** 6157,6169 **** { if (TREE_CODE (constructor_type) == ARRAY_TYPE) { ! if (tree_int_cst_equal (elt->purpose, ! constructor_unfilled_index)) ! output_init_element (elt->value, true, TREE_TYPE (constructor_type), ! constructor_unfilled_index, 0); ! else if (tree_int_cst_lt (constructor_unfilled_index, ! elt->purpose)) { /* Advance to the next smaller node. */ if (elt->left) --- 6289,6301 ---- { if (TREE_CODE (constructor_type) == ARRAY_TYPE) { ! int cmp = compare_tree_int (elt->purpose, ! aconstructor_unfilled_index); ! if (cmp == 0) ! output_array_init_element (elt->value, true, TREE_TYPE (constructor_type), ! aconstructor_unfilled_index, 0); ! else if (cmp >= 0) { /* Advance to the next smaller node. */ if (elt->left) *************** output_pending_init_elements (int all) *** 6188,6195 **** while (elt->parent && elt->parent->right == elt) elt = elt->parent; elt = elt->parent; ! if (elt && tree_int_cst_lt (constructor_unfilled_index, ! elt->purpose)) { next = elt->purpose; break; --- 6320,6327 ---- while (elt->parent && elt->parent->right == elt) elt = elt->parent; elt = elt->parent; ! if (elt && compare_tree_int (elt->purpose, ! aconstructor_unfilled_index) >= 0) { next = elt->purpose; break; *************** output_pending_init_elements (int all) *** 6264,6270 **** || TREE_CODE (constructor_type) == UNION_TYPE) constructor_unfilled_fields = next; else if (TREE_CODE (constructor_type) == ARRAY_TYPE) ! constructor_unfilled_index = next; /* ELT now points to the node in the pending tree with the next initializer to output. */ --- 6396,6402 ---- || TREE_CODE (constructor_type) == UNION_TYPE) constructor_unfilled_fields = next; else if (TREE_CODE (constructor_type) == ARRAY_TYPE) ! aconstructor_unfilled_index = TREE_INT_CST_LOW (next); /* ELT now points to the node in the pending tree with the next initializer to output. */ *************** process_init_element (struct c_expr valu *** 6295,6301 **** && constructor_type && TREE_CODE (constructor_type) == ARRAY_TYPE && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type)) ! && integer_zerop (constructor_unfilled_index)) { if (constructor_stack->replacement_value.value) error_init ("excess elements in char array initializer"); --- 6427,6433 ---- && constructor_type && TREE_CODE (constructor_type) == ARRAY_TYPE && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type)) ! && aconstructor_unfilled_index == 0) { if (constructor_stack->replacement_value.value) error_init ("excess elements in char array initializer"); *************** process_init_element (struct c_expr valu *** 6324,6331 **** process_init_element (pop_init_level (1)); else if (TREE_CODE (constructor_type) == ARRAY_TYPE && (constructor_max_index == 0 ! || tree_int_cst_lt (constructor_max_index, ! constructor_index))) process_init_element (pop_init_level (1)); else break; --- 6456,6463 ---- process_init_element (pop_init_level (1)); else if (TREE_CODE (constructor_type) == ARRAY_TYPE && (constructor_max_index == 0 ! || compare_tree_int (constructor_max_index, ! aconstructor_index) == -1)) process_init_element (pop_init_level (1)); else break; *************** process_init_element (struct c_expr valu *** 6518,6524 **** } if (constructor_max_index != 0 ! && (tree_int_cst_lt (constructor_max_index, constructor_index) || integer_all_onesp (constructor_max_index))) { pedwarn_init ("excess elements in array initializer"); --- 6650,6656 ---- } if (constructor_max_index != 0 ! && (compare_tree_int (constructor_max_index, aconstructor_index) == -1 || integer_all_onesp (constructor_max_index))) { pedwarn_init ("excess elements in array initializer"); *************** process_init_element (struct c_expr valu *** 6528,6547 **** /* Now output the actual element. */ if (value.value) { ! push_array_bounds (tree_low_cst (constructor_index, 0)); ! output_init_element (value.value, strict_string, ! elttype, constructor_index, 1); RESTORE_SPELLING_DEPTH (constructor_depth); } ! constructor_index ! = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); if (!value.value) /* If we are doing the bookkeeping for an element that was directly output as a constructor, we must update constructor_unfilled_index. */ ! constructor_unfilled_index = constructor_index; } else if (TREE_CODE (constructor_type) == VECTOR_TYPE) { --- 6660,6678 ---- /* Now output the actual element. */ if (value.value) { ! push_array_bounds (aconstructor_index); ! output_array_init_element (value.value, strict_string, ! elttype, aconstructor_index, 1); RESTORE_SPELLING_DEPTH (constructor_depth); } ! ++aconstructor_index; if (!value.value) /* If we are doing the bookkeeping for an element that was directly output as a constructor, we must update constructor_unfilled_index. */ ! aconstructor_unfilled_index = aconstructor_index; } else if (TREE_CODE (constructor_type) == VECTOR_TYPE) { Index: expr.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/expr.c,v retrieving revision 1.818 diff -c -3 -p -r1.818 expr.c *** expr.c 20 Sep 2005 21:16:40 -0000 1.818 --- expr.c 3 Oct 2005 17:34:18 -0000 *************** categorize_ctor_elements_1 (tree ctor, H *** 4413,4419 **** HOST_WIDE_INT mult; mult = 1; ! if (TREE_CODE (purpose) == RANGE_EXPR) { tree lo_index = TREE_OPERAND (purpose, 0); tree hi_index = TREE_OPERAND (purpose, 1); --- 4413,4419 ---- HOST_WIDE_INT mult; mult = 1; ! if (purpose && TREE_CODE (purpose) == RANGE_EXPR) { tree lo_index = TREE_OPERAND (purpose, 0); tree hi_index = TREE_OPERAND (purpose, 1); Index: gimplify.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v retrieving revision 2.156 diff -c -3 -p -r2.156 gimplify.c *** gimplify.c 3 Oct 2005 08:43:45 -0000 2.156 --- gimplify.c 3 Oct 2005 17:34:25 -0000 *************** gimplify_init_ctor_eval (tree object, VE *** 2616,2622 **** { tree array_elt_type = NULL; unsigned HOST_WIDE_INT ix; ! tree purpose, value; if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE) array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object))); --- 2616,2622 ---- { tree array_elt_type = NULL; unsigned HOST_WIDE_INT ix; ! tree purpose, value, last_purpose = integer_minus_one_node; if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE) array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object))); *************** gimplify_init_ctor_eval (tree object, VE *** 2633,2640 **** continue; /* ??? Here's to hoping the front end fills in all of the indices, ! so we don't have to figure out what's missing ourselves. */ ! gcc_assert (purpose); /* Skip zero-sized fields, unless value has side-effects. This can happen with calls to functions returning a zero-sized type, which --- 2633,2643 ---- continue; /* ??? Here's to hoping the front end fills in all of the indices, ! so we don't have to figure out what's missing ourselves. ! gcc_assert (purpose); */ ! if (!purpose) ! purpose = int_const_binop (PLUS_EXPR, last_purpose, integer_one_node, 0); ! last_purpose = purpose; /* Skip zero-sized fields, unless value has side-effects. This can happen with calls to functions returning a zero-sized type, which Index: tree.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree.c,v retrieving revision 1.506 diff -c -3 -p -r1.506 tree.c *** tree.c 3 Oct 2005 08:43:45 -0000 1.506 --- tree.c 3 Oct 2005 17:34:35 -0000 *************** int_cst_hash_hash (const void *x) *** 713,719 **** 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) --- 713,723 ---- tree t = (tree) x; return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t) ! ^ htab_hash_pointer (TREE_TYPE (t))); ! #if 0 ! return (TREE_INT_CST_HIGH (t) + TREE_INT_CST_LOW (t) ! + (long)TREE_TYPE (t)); ! #endif } /* Return nonzero if the value represented by *X (an INTEGER_CST tree node) Index: varasm.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/varasm.c,v retrieving revision 1.529 diff -c -3 -p -r1.529 varasm.c *** varasm.c 18 Sep 2005 17:11:11 -0000 1.529 --- varasm.c 3 Oct 2005 17:34:41 -0000 *************** array_size_for_constructor (tree val) *** 4009,4014 **** --- 4009,4015 ---- { tree max_index, i; unsigned HOST_WIDE_INT cnt; + HOST_WIDE_INT last_index = -1; tree index, value; /* This code used to attempt to handle string constants that are not *************** array_size_for_constructor (tree val) *** 4020,4030 **** --- 4021,4046 ---- max_index = NULL_TREE; FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (val), cnt, index, value) { + if (index == NULL_TREE) + { + ++last_index; + continue; + } if (TREE_CODE (index) == RANGE_EXPR) index = TREE_OPERAND (index, 1); if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index)) max_index = index; + if (index) + { + if (!max_index + || compare_tree_int (max_index, last_index) == -1) + max_index = build_int_cst (bitsizetype, last_index); + last_index = TREE_INT_CST_LOW (index); + } } + if (!max_index + || compare_tree_int (max_index, last_index) == -1) + max_index = build_int_cst (bitsizetype, last_index); if (max_index == NULL_TREE) return 0;