aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1998-05-18 06:21:14 -0700
committerRichard Henderson <rth@gcc.gnu.org>1998-05-18 06:21:14 -0700
commitead1705900f4e5c6e06407208b928d83b4646320 (patch)
tree52f254790542ea9c24b53b11b490678708eeaa15 /gcc/expr.c
parent6d73fddc3f93058d8f3534a3b888779a134c484e (diff)
downloadgcc-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.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 34f744d..f4e1d21 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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