diff options
Diffstat (limited to 'contrib/gcc/expr.c')
-rw-r--r-- | contrib/gcc/expr.c | 73 |
1 files changed, 61 insertions, 12 deletions
diff --git a/contrib/gcc/expr.c b/contrib/gcc/expr.c index c6bc426..1773fa1 100644 --- a/contrib/gcc/expr.c +++ b/contrib/gcc/expr.c @@ -5654,7 +5654,6 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, enum machine_mode mode = VOIDmode; tree offset = size_zero_node; tree bit_offset = bitsize_zero_node; - tree tem; /* First get the mode, signedness, and size. We do this from just the outermost expression. */ @@ -5690,6 +5689,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, *pbitsize = tree_low_cst (size_tree, 1); } + *pmode = mode; + /* Compute cumulative bit-offset for nested component-refs and array-refs, and find the ultimate containing object. */ while (1) @@ -5774,21 +5775,69 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, done: /* If OFFSET is constant, see if we can return the whole thing as a - constant bit position. Otherwise, split it up. */ - if (host_integerp (offset, 0) - && 0 != (tem = size_binop (MULT_EXPR, - fold_convert (bitsizetype, offset), - bitsize_unit_node)) - && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset)) - && host_integerp (tem, 0)) - *pbitpos = tree_low_cst (tem, 0), *poffset = 0; - else - *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset; + constant bit position. Make sure to handle overflow during + this conversion. */ + if (host_integerp (offset, 0)) + { + double_int tem = double_int_mul (tree_to_double_int (offset), + uhwi_to_double_int (BITS_PER_UNIT)); + tem = double_int_add (tem, tree_to_double_int (bit_offset)); + if (double_int_fits_in_shwi_p (tem)) + { + *pbitpos = double_int_to_shwi (tem); + *poffset = NULL_TREE; + return exp; + } + } + + /* Otherwise, split it up. */ + *pbitpos = tree_low_cst (bit_offset, 0); + *poffset = offset; - *pmode = mode; return exp; } +/* Given an expression EXP that may be a COMPONENT_REF or an ARRAY_REF, + look for whether EXP or any nested component-refs within EXP is marked + as PACKED. */ + +bool +contains_packed_reference (tree exp) +{ + bool packed_p = false; + + while (1) + { + switch (TREE_CODE (exp)) + { + case COMPONENT_REF: + { + tree field = TREE_OPERAND (exp, 1); + packed_p = DECL_PACKED (field) + || TYPE_PACKED (TREE_TYPE (field)) + || TYPE_PACKED (TREE_TYPE (exp)); + if (packed_p) + goto done; + } + break; + + case BIT_FIELD_REF: + case ARRAY_REF: + case ARRAY_RANGE_REF: + case REALPART_EXPR: + case IMAGPART_EXPR: + case VIEW_CONVERT_EXPR: + break; + + default: + goto done; + } + exp = TREE_OPERAND (exp, 0); + } + done: + return packed_p; +} + /* Return a tree of sizetype representing the size, in bytes, of the element of EXP, an ARRAY_REF. */ |