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:
parent
5b67ad6f45
commit
85f3d674d4
@ -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
|
||||
|
30
gcc/expr.c
30
gcc/expr.c
@ -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)
|
||||
|
89
gcc/varasm.c
89
gcc/varasm.c
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user