diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 2000-08-30 02:00:55 +0000 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 2000-08-29 22:00:55 -0400 |
commit | 85f3d674d453d980199d404c188b217dcc6ee9c1 (patch) | |
tree | 93a77b8da110b5aa2e972ff4785ebafed42b4547 /gcc | |
parent | 5b67ad6f4566834f8c0ffb253769727307bf0a11 (diff) | |
download | gcc-85f3d674d453d980199d404c188b217dcc6ee9c1.zip gcc-85f3d674d453d980199d404c188b217dcc6ee9c1.tar.gz gcc-85f3d674d453d980199d404c188b217dcc6ee9c1.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/expr.c | 30 | ||||
-rw-r--r-- | gcc/varasm.c | 89 |
3 files changed, 73 insertions, 56 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 37417b7..2897519 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 @@ -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) diff --git a/gcc/varasm.c b/gcc/varasm.c index 5193dd6..478daf8 100644 --- a/gcc/varasm.c +++ b/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); } |