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]

C PATCH: Don't generate initializers incrementally



This patch gets rid of lots of code in c-typeck.c designed to emit
little bits of big global array/structure initializers at a time.

That's silly -- we actually should save them all up to end of file and
then emit them only if we really need to.  But, I didn't do that. :-)

This is a partial step; we do just save up the CONSTRUCTOR nodes and
emit them when we're done with the whole declaration, just like in
C++.  This has the side-effect (requested privately by several people)
that DECL_INITIAL for a global array is now set correctly throughout
the compilation, rather than being set to error_mark_node.

(BTW, I'm really psyched about how many people are already using GCC's
function-at-a-time stuff for non-compiler purposes.  Our own Ben Chelf
is busy finding Linux and BSD kernel bugs, for example -- see
http://www.stanford.edu/~engler/mc-osdi.ps for example.)

Bootstrapped/tested on i686-pc-linux-gnu.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2000-10-27  Mark Mitchell  <mark@codesourcery.com>

	* c-typeck.c (check_init_type_bitfields): Remove.
	(constructor_incremental): Likewise.
	(struct constructor_stack): Remove incremental bit.
	(struct initializer_stack): Likewise.
	(start_init): Don't play with constructor_incremental.
	(finish_init): Likewise.
	(really_start_incremental_init): Likewise.
	(push_init_level): Likewise.
	(pop_init_level): Liekwise.
	(output_init_level): Likewise.
	(output_pending_init_elements): Likewise.

2000-10-27  Mark Mitchell  <mark@codesourcery.com>

	* gcc.dg/noncompile/init-2.c: Tweak to deal with multiple errors
	on the same line.

Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-typeck.c,v
retrieving revision 1.96
diff -c -p -r1.96 c-typeck.c
*** c-typeck.c	2000/10/20 15:59:06	1.96
--- c-typeck.c	2000/10/28 00:10:15
*************** static int spelling_length		PARAMS ((voi
*** 74,80 ****
  static char *print_spelling		PARAMS ((char *));
  static void warning_init		PARAMS ((const char *));
  static tree digest_init			PARAMS ((tree, tree, int, int));
- static void check_init_type_bitfields	PARAMS ((tree));
  static void output_init_element		PARAMS ((tree, tree, tree, int));
  static void output_pending_init_elements PARAMS ((int));
  static void add_pending_init		PARAMS ((tree, tree));
--- 74,79 ----
*************** int constructor_no_implicit = 0; /* 0 fo
*** 4900,4909 ****
  static int require_constant_value;
  static int require_constant_elements;
  
- /* 1 if it is ok to output this constructor as we read it.
-    0 means must accumulate a CONSTRUCTOR expression.  */
- static int constructor_incremental;
- 
  /* DECL node for which an initializer is being read.
     0 means we are reading a constructor expression
     such as (struct foo) {...}.  */
--- 4899,4904 ----
*************** struct constructor_stack
*** 4941,4947 ****
    char constant;
    char simple;
    char implicit;
-   char incremental;
    char erroneous;
    char outer;
  };
--- 4936,4941 ----
*************** struct initializer_stack
*** 4963,4969 ****
    struct spelling *spelling_base;
    int spelling_size;
    char top_level;
-   char incremental;
    char require_constant_value;
    char require_constant_elements;
    char deferred;
--- 4957,4962 ----
*************** start_init (decl, asmspec_tree, top_leve
*** 4989,4995 ****
  
    p->decl = constructor_decl;
    p->asmspec = constructor_asmspec;
-   p->incremental = constructor_incremental;
    p->require_constant_value = require_constant_value;
    p->require_constant_elements = require_constant_elements;
    p->constructor_stack = constructor_stack;
--- 4982,4987 ----
*************** start_init (decl, asmspec_tree, top_leve
*** 5003,5009 ****
    initializer_stack = p;
  
    constructor_decl = decl;
-   constructor_incremental = top_level;
    constructor_asmspec = asmspec;
    constructor_subconstants_deferred = 0;
    constructor_top_level = top_level;
--- 4995,5000 ----
*************** start_init (decl, asmspec_tree, top_leve
*** 5020,5027 ****
  	       || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
  	       || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
        locus = IDENTIFIER_POINTER (DECL_NAME (decl));
-       constructor_incremental 
- 	|= (TREE_STATIC (decl) && !DECL_CONTEXT (decl));
      }
    else
      {
--- 5011,5016 ----
*************** finish_init ()
*** 5064,5070 ****
    /* Pop back to the data of the outer initializer (if any).  */
    constructor_decl = p->decl;
    constructor_asmspec = p->asmspec;
-   constructor_incremental = p->incremental;
    require_constant_value = p->require_constant_value;
    require_constant_elements = p->require_constant_elements;
    constructor_stack = p->constructor_stack;
--- 5053,5058 ----
*************** really_start_incremental_init (type)
*** 5095,5105 ****
    if (type == 0)
      type = TREE_TYPE (constructor_decl);
  
-   /* Turn off constructor_incremental if type is a struct with bitfields.
-      Do this before the first push, so that the corrected value
-      is available in finish_init.  */
-   check_init_type_bitfields (type);
- 
    p->type = constructor_type;
    p->fields = constructor_fields;
    p->index = constructor_index;
--- 5083,5088 ----
*************** really_start_incremental_init (type)
*** 5116,5122 ****
    p->depth = constructor_depth;
    p->replacement_value = 0;
    p->implicit = 0;
-   p->incremental = constructor_incremental;
    p->outer = 0;
    p->next = 0;
    constructor_stack = p;
--- 5099,5104 ----
*************** really_start_incremental_init (type)
*** 5162,5177 ****
        constructor_fields = constructor_type;
        constructor_unfilled_fields = constructor_type;
      }
- 
-   if (constructor_incremental)
-     {
-       make_decl_rtl (constructor_decl, constructor_asmspec,
- 		     constructor_top_level);
-       assemble_variable (constructor_decl, constructor_top_level, 0, 1);
- 
-       defer_addressed_constants ();
-       constructor_subconstants_deferred = 1;
-     }
  }
  
  /* Push down into a subobject, for initialization.
--- 5144,5149 ----
*************** push_init_level (implicit)
*** 5200,5229 ****
  	break;
      }
  
-   /* Structure elements may require alignment.  Do this now if necessary
-      for the subaggregate, and if it comes next in sequence.  Don't do
-      this for subaggregates that will go on the pending list.  */
-   if (constructor_incremental && constructor_type != 0
-       && TREE_CODE (constructor_type) == RECORD_TYPE && constructor_fields
-       && constructor_fields == constructor_unfilled_fields)
-     {
-       /* Advance to offset of this element.  */
-       if (! tree_int_cst_equal (constructor_bit_index,
- 				bit_position (constructor_fields)))
- 	assemble_zeros
- 	  (tree_low_cst
- 	   (size_binop (TRUNC_DIV_EXPR,
- 			size_binop (MINUS_EXPR,
- 				    bit_position (constructor_fields),
- 				    constructor_bit_index),
- 			bitsize_unit_node),
- 	    1));
- 
-       /* Indicate that we have now filled the structure up to the current
- 	 field.  */
-       constructor_unfilled_fields = constructor_fields;
-     }
- 
    p = (struct constructor_stack *) xmalloc (sizeof (struct constructor_stack));
    p->type = constructor_type;
    p->fields = constructor_fields;
--- 5172,5177 ----
*************** push_init_level (implicit)
*** 5241,5247 ****
    p->depth = constructor_depth;
    p->replacement_value = 0;
    p->implicit = implicit;
-   p->incremental = constructor_incremental;
    p->outer = 0;
    p->next = constructor_stack;
    constructor_stack = p;
--- 5189,5194 ----
*************** push_init_level (implicit)
*** 5267,5274 ****
  	  constructor_type = TREE_TYPE (constructor_fields);
  	  push_member_name (constructor_fields);
  	  constructor_depth++;
- 	  if (constructor_fields != constructor_unfilled_fields)
- 	    constructor_incremental = 0;
  	}
      }
    else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
--- 5214,5219 ----
*************** push_init_level (implicit)
*** 5276,5284 ****
        constructor_type = TREE_TYPE (constructor_type);
        push_array_bounds (tree_low_cst (constructor_index, 0));
        constructor_depth++;
-       if (! tree_int_cst_equal (constructor_index, constructor_unfilled_index)
- 	  || constructor_range_end != 0)
- 	constructor_incremental = 0;
      }
  
    if (constructor_type == 0)
--- 5221,5226 ----
*************** push_init_level (implicit)
*** 5289,5297 ****
        return;
      }
  
-   /* Turn off constructor_incremental if type is a struct with bitfields.  */
-   check_init_type_bitfields (constructor_type);
- 
    if (implicit && warn_missing_braces && !missing_braces_mentioned)
      {
        missing_braces_mentioned = 1;
--- 5231,5236 ----
*************** push_init_level (implicit)
*** 5335,5379 ****
      }
  }
  
- /* Don't read a struct incrementally if it has any bitfields,
-    because the incremental reading code doesn't know how to
-    handle bitfields yet.  */
- 
- static void
- check_init_type_bitfields (type)
-      tree type;
- {
-   if (TREE_CODE (type) == RECORD_TYPE)
-     {
-       tree tail;
-       for (tail = TYPE_FIELDS (type); tail;
- 	   tail = TREE_CHAIN (tail))
- 	{
- 	  if (DECL_C_BIT_FIELD (tail))
- 	    {
- 	      constructor_incremental = 0;
- 	      break;
- 	    }
- 
- 	  check_init_type_bitfields (TREE_TYPE (tail));
- 	}
-     }
- 
-   else if (TREE_CODE (type) == UNION_TYPE)
-     {
-       tree tail = TYPE_FIELDS (type);
-       if (tail && DECL_C_BIT_FIELD (tail))
- 	/* We also use the nonincremental algorithm for initiliazation
- 	   of unions whose first member is a bitfield, becuase the
- 	   incremental algorithm has no code for dealing with
- 	   bitfields. */
- 	constructor_incremental = 0;
-     }
- 
-   else if (TREE_CODE (type) == ARRAY_TYPE)
-     check_init_type_bitfields (TREE_TYPE (type));
- }
- 
  /* At the end of an implicit or explicit brace level, 
     finish up that level of constructor.
     If we were outputting the elements as they are read, return 0
--- 5274,5279 ----
*************** pop_init_level (implicit)
*** 5429,5473 ****
    /* Pad out the end of the structure.  */
    
    if (p->replacement_value)
!     {
!       /* If this closes a superfluous brace pair,
! 	 just pass out the element between them.  */
!       constructor = p->replacement_value;
!       /* If this is the top level thing within the initializer,
! 	 and it's for a variable, then since we already called
! 	 assemble_variable, we must output the value now.  */
!       if (p->next == 0 && constructor_decl != 0
! 	  && constructor_incremental)
! 	{
! 	  constructor = digest_init (constructor_type, constructor,
! 				     require_constant_value,
! 				     require_constant_elements);
! 
! 	  /* If initializing an array of unknown size,
! 	     determine the size now.  */
! 	  if (TREE_CODE (constructor_type) == ARRAY_TYPE
! 	      && TYPE_DOMAIN (constructor_type) == 0)
! 	    {
! 	      /* We shouldn't have an incomplete array type within
! 		 some other type.  */
! 	      if (constructor_stack->next)
! 		abort ();
! 
! 	      if (complete_array_type (constructor_type, constructor, 0))
! 		abort ();
! 
! 	      size = int_size_in_bytes (constructor_type);
! 	    }
! 
! 	  output_constant (constructor, size);
! 	}
!     }
    else if (constructor_type == 0)
      ;
    else if (TREE_CODE (constructor_type) != RECORD_TYPE
  	   && TREE_CODE (constructor_type) != UNION_TYPE
! 	   && TREE_CODE (constructor_type) != ARRAY_TYPE
! 	   && ! constructor_incremental)
      {
        /* A nonincremental scalar initializer--just return
  	 the element, after verifying there is just one.  */
--- 5329,5342 ----
    /* Pad out the end of the structure.  */
    
    if (p->replacement_value)
!     /* If this closes a superfluous brace pair,
!        just pass out the element between them.  */
!     constructor = p->replacement_value;
    else if (constructor_type == 0)
      ;
    else if (TREE_CODE (constructor_type) != RECORD_TYPE
  	   && TREE_CODE (constructor_type) != UNION_TYPE
! 	   && TREE_CODE (constructor_type) != ARRAY_TYPE)
      {
        /* A nonincremental scalar initializer--just return
  	 the element, after verifying there is just one.  */
*************** pop_init_level (implicit)
*** 5484,5490 ****
        else
  	constructor = TREE_VALUE (constructor_elements);
      }
!   else if (! constructor_incremental)
      {
        if (constructor_erroneous)
  	constructor = error_mark_node;
--- 5353,5359 ----
        else
  	constructor = TREE_VALUE (constructor_elements);
      }
!   else
      {
        if (constructor_erroneous)
  	constructor = error_mark_node;
*************** pop_init_level (implicit)
*** 5498,5555 ****
  	    TREE_STATIC (constructor) = 1;
  	}
      }
-   else
-     {
-       tree filled;
- 
-       if (TREE_CODE (constructor_type) == RECORD_TYPE
- 	  || TREE_CODE (constructor_type) == UNION_TYPE)
- 	/* Find the offset of the end of that field.  */
- 	filled = size_binop (CEIL_DIV_EXPR, constructor_bit_index,
- 			     bitsize_unit_node);
- 
-       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- 	{
- 	  /* If initializing an array of unknown size,
- 	     determine the size now.  */
- 	  if (TREE_CODE (constructor_type) == ARRAY_TYPE
- 	      && TYPE_DOMAIN (constructor_type) == 0)
- 	    {
- 	      tree maxindex
- 		= copy_node (size_diffop (constructor_unfilled_index,
- 					  bitsize_one_node));
- 
- 	      TYPE_DOMAIN (constructor_type) = build_index_type (maxindex);
- 	      TREE_TYPE (maxindex) = TYPE_DOMAIN (constructor_type);
- 
- 	      /* TYPE_MAX_VALUE is always one less than the number of elements
- 		 in the array, because we start counting at zero.  Therefore,
- 		 warn only if the value is less than zero.  */
- 	      if (pedantic
- 		  && (tree_int_cst_sgn
- 		      (TYPE_MAX_VALUE (TYPE_DOMAIN (constructor_type)))
- 		      < 0))
- 		error_with_decl (constructor_decl,
- 				 "zero or negative array size `%s'");
- 
- 	      layout_type (constructor_type);
- 	      size = int_size_in_bytes (constructor_type);
- 	    }
- 
- 	  filled
- 	    = size_binop (MULT_EXPR, constructor_unfilled_index,
- 			  convert (bitsizetype,
- 				   TYPE_SIZE_UNIT
- 				   (TREE_TYPE (constructor_type))));
- 	}
-       else
- 	filled = 0;
- 
-       if (filled != 0)
- 	assemble_zeros (size - tree_low_cst (filled, 1));
-     }
  
- 	  
    constructor_type = p->type;
    constructor_fields = p->fields;
    constructor_index = p->index;
--- 5367,5373 ----
*************** pop_init_level (implicit)
*** 5564,5570 ****
    constructor_erroneous = p->erroneous;
    constructor_pending_elts = p->pending_elts;
    constructor_depth = p->depth;
-   constructor_incremental = p->incremental;
    RESTORE_SPELLING_DEPTH (constructor_depth);
  
    constructor_stack = p->next;
--- 5382,5387 ----
*************** output_init_element (value, type, field,
*** 6002,6046 ****
  
        if (!duplicate)
  	{
! 	  if (! constructor_incremental)
! 	    {
! 	      if (field && TREE_CODE (field) == INTEGER_CST)
! 		field = copy_node (field);
! 	      constructor_elements
! 		= tree_cons (field, digest_init (type, value,
! 						 require_constant_value, 
! 						 require_constant_elements),
! 			     constructor_elements);
! 	    }
! 	  else
! 	    {
! 	      /* Structure elements may require alignment.
! 		 Do this, if necessary.  */
! 	      if (TREE_CODE (constructor_type) == RECORD_TYPE
! 		  && ! tree_int_cst_equal (constructor_bit_index,
! 					   bit_position (field)))
! 		/* Advance to offset of this element.  */
! 		assemble_zeros
! 		  (tree_low_cst
! 		   (size_binop (TRUNC_DIV_EXPR,
! 				size_binop (MINUS_EXPR, bit_position (field),
! 					    constructor_bit_index),
! 				bitsize_unit_node),
! 		    0));
! 
! 	      output_constant (digest_init (type, value,
! 					    require_constant_value,
! 					    require_constant_elements),
! 			       int_size_in_bytes (type));
! 
! 	      /* For a record or union,
! 		 keep track of end position of last field.  */
! 	      if (TREE_CODE (constructor_type) == RECORD_TYPE
! 		  || TREE_CODE (constructor_type) == UNION_TYPE)
! 		constructor_bit_index
! 		  = size_binop (PLUS_EXPR, bit_position (field),
! 				DECL_SIZE (field));
! 	    }
  	}
  
        /* Advance the variable that indicates sequential elements output.  */
--- 5819,5831 ----
  
        if (!duplicate)
  	{
! 	  if (field && TREE_CODE (field) == INTEGER_CST)
! 	    field = copy_node (field);
! 	  constructor_elements
! 	    = tree_cons (field, digest_init (type, value,
! 					     require_constant_value, 
! 					     require_constant_elements),
! 			 constructor_elements);
  	}
  
        /* Advance the variable that indicates sequential elements output.  */
*************** output_pending_init_elements (all)
*** 6195,6261 ****
       and there are elements left.  */
    if (! (all && next != 0))
      return;
- 
-   /* Generate space up to the position of NEXT.  */
-   if (constructor_incremental)
-     {
-       tree filled;
-       tree nextpos_tree = bitsize_zero_node;
- 
-       if (TREE_CODE (constructor_type) == RECORD_TYPE
- 	  || TREE_CODE (constructor_type) == UNION_TYPE)
- 	{
- 	  tree tail;
- 
- 	  /* Find the last field written out, if any.  */
- 	  for (tail = TYPE_FIELDS (constructor_type); tail;
- 	       tail = TREE_CHAIN (tail))
- 	    if (TREE_CHAIN (tail) == constructor_unfilled_fields)
- 	      break;
- 
- 	  if (tail)
- 	    /* Find the offset of the end of that field.  */
- 	    filled = size_binop (CEIL_DIV_EXPR,
- 				 size_binop (PLUS_EXPR, bit_position (tail),
- 					     DECL_SIZE (tail)),
- 				 bitsize_unit_node);
- 	  else
- 	    filled = bitsize_zero_node;
- 
- 	  nextpos_tree = convert (bitsizetype, byte_position (next));
- 	  constructor_bit_index = bit_position (next);
- 	  constructor_unfilled_fields = next;
- 	}
-       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
- 	{
- 	  filled
- 	    = size_binop (MULT_EXPR, constructor_unfilled_index,
- 			  convert (bitsizetype,
- 				   TYPE_SIZE_UNIT
- 				   (TREE_TYPE (constructor_type))));
- 	  nextpos_tree
- 	    = size_binop (MULT_EXPR, next,
- 			  convert (bitsizetype, TYPE_SIZE_UNIT
- 				   (TREE_TYPE (constructor_type))));
- 	  constructor_unfilled_index = next;
- 	}
-       else
- 	filled = 0;
  
!       if (filled)
! 	assemble_zeros (tree_low_cst (size_diffop (nextpos_tree, filled), 1));
!     }
!   else
!     {
!       /* If it's not incremental, just skip over the gap,
! 	 so that after jumping to retry we will output the next
! 	 successive element.  */
!       if (TREE_CODE (constructor_type) == RECORD_TYPE
! 	  || 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.  */
--- 5980,5993 ----
       and there are elements left.  */
    if (! (all && next != 0))
      return;
  
!   /* If it's not incremental, just skip over the gap, so that after
!      jumping to retry we will output the next successive element.  */
!   if (TREE_CODE (constructor_type) == RECORD_TYPE
!       || 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.  */
*************** output_pending_init_elements (all)
*** 6268,6280 ****
     to handle a partly-braced initializer.
  
     Once this has found the correct level for the new element,
!    it calls output_init_element.
! 
!    Note: if we are incrementally outputting this constructor,
!    this function may be called with a null argument
!    representing a sub-constructor that was already incrementally output.
!    When that happens, we output nothing, but we do the bookkeeping
!    to skip past that element of the current constructor.  */
  
  void
  process_init_element (value)
--- 6000,6006 ----
     to handle a partly-braced initializer.
  
     Once this has found the correct level for the new element,
!    it calls output_init_element.  */
  
  void
  process_init_element (value)
Index: testsuite/gcc.dg/noncompile/init-2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/gcc.dg/noncompile/init-2.c,v
retrieving revision 1.1
diff -c -p -r1.1 init-2.c
*** init-2.c	2000/06/29 19:55:26	1.1
--- init-2.c	2000/10/28 00:10:19
***************
*** 1 ****
! int d[][] = { {1}, {2}, {3} };	/* { dg-error "incomplete type" } */
--- 1 ----
! int d[][] = { {1}, {2}, {3} };	/* { dg-error "incomplete type|storage size|one element" } */

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