This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]