expr.c (store_constructor): Allow variable bounds of array type.

* expr.c (store_constructor): Allow variable bounds of array type.
	(expand_expr): Don't blow up if type is ERROR_MARK.
	* varasm.c (output_constructor): Don't access lower bound of array
	type unless need it if index is supplied (so it can be a variable
	if no index is supplied).
	Use tree_low_cst; use HOST_WIDE_INT for sizes; change BITPOS to POS.
	Other minor cleanups.

From-SVN: r36060
This commit is contained in:
Richard Kenner 2000-08-30 02:00:55 +00:00 committed by Richard Kenner
parent 5b67ad6f45
commit 85f3d674d4
3 changed files with 73 additions and 56 deletions

View File

@ -1,3 +1,13 @@
Tue Aug 29 22:09:59 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* expr.c (store_constructor): Allow variable bounds of array type.
(expand_expr): Don't blow up if type is ERROR_MARK.
* varasm.c (output_constructor): Don't access lower bound of array
type unless need it if index is supplied (so it can be a variable
if no index is supplied).
Use tree_low_cst; use HOST_WIDE_INT for sizes; change BITPOS to POS.
Other minor cleanups.
2000-08-29 J. David Anglin <dave@hiauly1.hia.nrc.ca>
* Makefile.in: Revamp handling of cflags to allow different WARN_CFLAGS

View File

@ -4397,9 +4397,18 @@ store_constructor (exp, target, align, cleared, size)
register int i;
int need_to_clear;
tree domain = TYPE_DOMAIN (type);
HOST_WIDE_INT minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
HOST_WIDE_INT maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
tree elttype = TREE_TYPE (type);
int const_bounds_p = (host_integerp (TYPE_MIN_VALUE (domain), 0)
&& host_integerp (TYPE_MAX_VALUE (domain), 0));
HOST_WIDE_INT minelt;
HOST_WIDE_INT maxelt;
/* If we have constant bounds for the range of the type, get them. */
if (const_bounds_p)
{
minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
}
/* If the constructor has fewer elements than the array,
clear the whole array first. Similarly if this is
@ -4409,12 +4418,13 @@ store_constructor (exp, target, align, cleared, size)
else
{
HOST_WIDE_INT count = 0, zero_count = 0;
need_to_clear = 0;
need_to_clear = ! const_bounds_p;
/* This loop is a more accurate version of the loop in
mostly_zeros_p (it handles RANGE_EXPR in an index).
It is also needed to check for missing elements. */
for (elt = CONSTRUCTOR_ELTS (exp);
elt != NULL_TREE;
elt != NULL_TREE && ! need_to_clear;
elt = TREE_CHAIN (elt))
{
tree index = TREE_PURPOSE (elt);
@ -4437,16 +4447,19 @@ store_constructor (exp, target, align, cleared, size)
}
else
this_node_count = 1;
count += this_node_count;
if (mostly_zeros_p (TREE_VALUE (elt)))
zero_count += this_node_count;
}
/* Clear the entire array first if there are any missing elements,
or if the incidence of zero elements is >= 75%. */
if (count < maxelt - minelt + 1
|| 4 * zero_count >= 3 * count)
if (! need_to_clear
&& (count < maxelt - minelt + 1 || 4 * zero_count >= 3 * count))
need_to_clear = 1;
}
if (need_to_clear && size > 0)
{
if (! cleared)
@ -4495,7 +4508,8 @@ store_constructor (exp, target, align, cleared, size)
tree position;
/* If the range is constant and "small", unroll the loop. */
if (host_integerp (lo_index, 0)
if (const_bounds_p
&& host_integerp (lo_index, 0)
&& host_integerp (hi_index, 0)
&& (lo = tree_low_cst (lo_index, 0),
hi = tree_low_cst (hi_index, 0),
@ -5762,7 +5776,7 @@ expand_expr (exp, target, tmode, modifier)
enum expand_modifier ro_modifier;
/* Handle ERROR_MARK before anybody tries to access its type. */
if (TREE_CODE (exp) == ERROR_MARK)
if (TREE_CODE (exp) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
{
op0 = CONST0_RTX (tmode);
if (op0 != 0)

View File

@ -4361,11 +4361,12 @@ output_constructor (exp, size)
tree exp;
int size;
{
tree type = TREE_TYPE (exp);
register tree link, field = 0;
HOST_WIDE_INT min_index = 0;
tree min_index = 0;
/* Number of bytes output or skipped so far.
In other words, current position within the constructor. */
int total_bytes = 0;
HOST_WIDE_INT total_bytes = 0;
/* Non-zero means BYTE contains part of a byte, to be output. */
int byte_buffer_in_use = 0;
register int byte = 0;
@ -4373,13 +4374,12 @@ output_constructor (exp, size)
if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
abort ();
if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
field = TYPE_FIELDS (TREE_TYPE (exp));
if (TREE_CODE (type) == RECORD_TYPE)
field = TYPE_FIELDS (type);
if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
&& TYPE_DOMAIN (TREE_TYPE (exp)) != 0)
min_index
= TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (exp))));
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) != 0)
min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
/* As LINK goes through the elements of the constant,
FIELD goes through the structure fields, if the constant is a structure.
@ -4398,17 +4398,14 @@ output_constructor (exp, size)
tree val = TREE_VALUE (link);
tree index = 0;
/* the element in a union constructor specifies the proper field. */
/* The element in a union constructor specifies the proper field
or index. */
if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
&& TREE_PURPOSE (link) != 0)
field = TREE_PURPOSE (link);
if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)
{
/* if available, use the type given by link */
if (TREE_PURPOSE (link) != 0)
field = TREE_PURPOSE (link);
}
if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
else if (TREE_CODE (type) == ARRAY_TYPE)
index = TREE_PURPOSE (link);
/* Eliminate the marker that makes a cast not be an lvalue. */
@ -4418,10 +4415,11 @@ output_constructor (exp, size)
if (index && TREE_CODE (index) == RANGE_EXPR)
{
register int fieldsize
= int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
HOST_WIDE_INT lo_index = TREE_INT_CST_LOW (TREE_OPERAND (index, 0));
HOST_WIDE_INT hi_index = TREE_INT_CST_LOW (TREE_OPERAND (index, 1));
= int_size_in_bytes (TREE_TYPE (type));
HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
HOST_WIDE_INT index;
for (index = lo_index; index <= hi_index; index++)
{
/* Output the element's initial value. */
@ -4441,12 +4439,11 @@ output_constructor (exp, size)
register int fieldsize;
/* Since this structure is static,
we know the positions are constant. */
HOST_WIDE_INT bitpos = field ? int_byte_position (field) : 0;
HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
if (index != 0)
bitpos
= (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
* (tree_low_cst (index, 0) - min_index));
pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
* (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
/* Output any buffered-up bit-fields preceding this element. */
if (byte_buffer_in_use)
@ -4459,31 +4456,24 @@ output_constructor (exp, size)
/* Advance to offset of this element.
Note no alignment needed in an array, since that is guaranteed
if each element has the proper size. */
if ((field != 0 || index != 0) && bitpos != total_bytes)
if ((field != 0 || index != 0) && pos != total_bytes)
{
assemble_zeros (bitpos - total_bytes);
total_bytes = bitpos;
assemble_zeros (pos - total_bytes);
total_bytes = pos;
}
else if (field != 0 && DECL_PACKED (field))
{
/* Some assemblers automaticallly align a datum according to
its size if no align directive is specified. The datum,
however, may be declared with 'packed' attribute, so we
have to disable such a feature. */
ASM_OUTPUT_ALIGN (asm_out_file, 0);
}
else if (field != 0 && DECL_PACKED (field))
/* Some assemblers automaticallly align a datum according to its
size if no align directive is specified. The datum, however,
may be declared with 'packed' attribute, so we have to disable
such a feature. */
ASM_OUTPUT_ALIGN (asm_out_file, 0);
/* Determine size this element should occupy. */
if (field)
{
if (TREE_CODE (DECL_SIZE_UNIT (field)) != INTEGER_CST)
abort ();
fieldsize = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
}
fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
else
fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
fieldsize = int_size_in_bytes (TREE_TYPE (type));
/* Output the element's initial value. */
if (val == 0)
@ -4544,8 +4534,8 @@ output_constructor (exp, size)
int this_time;
int shift;
HOST_WIDE_INT value;
int next_byte = next_offset / BITS_PER_UNIT;
int next_bit = next_offset % BITS_PER_UNIT;
HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
/* Advance from byte to byte
within this element when necessary. */
@ -4566,6 +4556,7 @@ output_constructor (exp, size)
first (of the bits that are significant)
and put them into bytes from the most significant end. */
shift = end_offset - next_offset - this_time;
/* Don't try to take a bunch of bits that cross
the word boundary in the INTEGER_CST. We can
only select bits from the LOW or HIGH part
@ -4579,9 +4570,7 @@ output_constructor (exp, size)
/* Now get the bits from the appropriate constant word. */
if (shift < HOST_BITS_PER_WIDE_INT)
{
value = TREE_INT_CST_LOW (val);
}
value = TREE_INT_CST_LOW (val);
else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
{
value = TREE_INT_CST_HIGH (val);
@ -4589,6 +4578,7 @@ output_constructor (exp, size)
}
else
abort ();
/* Get the result. This works only when:
1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
byte |= (((value >> shift)
@ -4628,16 +4618,19 @@ output_constructor (exp, size)
& (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
<< next_bit);
}
next_offset += this_time;
byte_buffer_in_use = 1;
}
}
}
if (byte_buffer_in_use)
{
ASM_OUTPUT_BYTE (asm_out_file, byte);
total_bytes++;
}
if (total_bytes < size)
assemble_zeros (size - total_bytes);
}