diff options
author | Richard Henderson <rth@cygnus.com> | 1998-05-18 06:21:14 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1998-05-18 06:21:14 -0700 |
commit | ead1705900f4e5c6e06407208b928d83b4646320 (patch) | |
tree | 52f254790542ea9c24b53b11b490678708eeaa15 /gcc/expr.c | |
parent | 6d73fddc3f93058d8f3534a3b888779a134c484e (diff) | |
download | gcc-ead1705900f4e5c6e06407208b928d83b4646320.zip gcc-ead1705900f4e5c6e06407208b928d83b4646320.tar.gz gcc-ead1705900f4e5c6e06407208b928d83b4646320.tar.bz2 |
tree.h (TYPE_SIZE_UNIT): New.
* tree.h (TYPE_SIZE_UNIT): New.
(struct tree_type): Add size_unit member.
* stor-layout.c (layout_type): Initialize it.
* expr.c (get_inner_reference) [ARRAY_REF]: Use it.
* tree.c (size_in_bytes, int_size_in_bytes): Likewise.
From-SVN: r19853
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 31 |
1 files changed, 19 insertions, 12 deletions
@@ -4374,6 +4374,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node; tree index_type = TREE_TYPE (index); + tree xindex; if (TYPE_PRECISION (index_type) != TYPE_PRECISION (sizetype)) { @@ -4391,21 +4392,27 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, index_type = TREE_TYPE (index); } - index = fold (build (MULT_EXPR, sbitsizetype, index, - convert (sbitsizetype, - TYPE_SIZE (TREE_TYPE (exp))))); + xindex = fold (build (MULT_EXPR, sbitsizetype, index, + convert (sbitsizetype, + TYPE_SIZE (TREE_TYPE (exp))))); - if (TREE_CODE (index) == INTEGER_CST - && TREE_INT_CST_HIGH (index) == 0) - *pbitpos += TREE_INT_CST_LOW (index); + if (TREE_CODE (xindex) == INTEGER_CST + && TREE_INT_CST_HIGH (xindex) == 0) + *pbitpos += TREE_INT_CST_LOW (xindex); else { - if (contains_placeholder_p (index)) - index = build (WITH_RECORD_EXPR, sizetype, index, exp); - - offset = size_binop (PLUS_EXPR, offset, - size_binop (FLOOR_DIV_EXPR, index, - size_int (BITS_PER_UNIT))); + /* Either the bit offset calculated above is not constant, or + it overflowed. In either case, redo the multiplication + against the size in units. This is especially important + in the non-constant case to avoid a division at runtime. */ + xindex = fold (build (MULT_EXPR, ssizetype, index, + convert (ssizetype, + TYPE_SIZE_UNIT (TREE_TYPE (exp))))); + + if (contains_placeholder_p (xindex)) + xindex = build (WITH_RECORD_EXPR, sizetype, xindex, exp); + + offset = size_binop (PLUS_EXPR, offset, xindex); } } else if (TREE_CODE (exp) != NON_LVALUE_EXPR |