This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC][PATHC] Attack PR12245 by fiddling with CONSTRUCTOR
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc at gcc dot gnu dot org
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 3 Oct 2005 19:52:41 +0200 (CEST)
- Subject: [RFC][PATHC] Attack PR12245 by fiddling with CONSTRUCTOR
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;