Hello,

First a short description of a problem we are seeing, then a couple
of related questions on addressability checks in the gimplifier.

>From a simple Ada testcase which I can provide if need be, the front-end
is producing a MODIFY_EXPR with a lhs of the following shape when we get
to gimplify_modify_expr: 

 <array_range_ref 
    type <array_type p5__process__T6b
        size <var_decl D.632

    arg 0 <component_ref
        type <array_type p5__short_message__T4b
       
        arg 0 <var_decl sm type <record_type 
            BLK 
            size <integer_cst constant invariant 40>

        arg 1 <field_decl data type <array_type 
            external packed bit-field nonaddressable SI 
            align 1 offset_align 128
            offset <integer_cst constant invariant 0>
            bit offset <integer_cst constant invariant 1>

    arg 1 <integer_cst 0x401d9048 constant invariant 1>

in short, a variable size array_range_ref within a bitfield record component.

The lhs remains of similar shape after gimplification, the rhs is of
variable size as well, and we end up at this point in gimplify_modify_expr:

  /* If we've got a variable sized assignment between two lvalues (i.e. does
     not involve a call), then we can make things a bit more straightforward
     by converting the assignment to memcpy or memset.  */
  if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
    {
      tree from = TREE_OPERAND (*from_p, 0);
      tree size = TREE_OPERAND (*from_p, 1);

      if (TREE_CODE (from) == CONSTRUCTOR)
        return gimplify_modify_expr_to_memset (expr_p, size, want_value);
      if (is_gimple_addressable (from))
        {
          *from_p = from;
          return gimplify_modify_expr_to_memcpy (expr_p, size, want_value);
        }
    }

We get down into gimplify_modify_expr_to_memcpy, which builds ADDR_EXPRs
for both operands, which ICEs later on from expand_expr_addr_expr_1 because
the operand sketched above is not byte-aligned.

The first puzzle to me is that there is no check made that the target
is a valid argument for an ADDR_EXPR.  AFAICS, it has been gimplified
with is_gimple_lvalue/fb_lvalue as the predicate/fallback pair, but
this currently doesn't imply the required properties.

I first thought that a is_gimple_addressable (*to_p) addition to the
outer condition would help, but it actually does not because the
predicate is shallow and only checks a very restricted set of
conditions (e.g.  any ARRAY_RANGE_REF or COMPONENT_REF is considered
"addressable"). This is actually the reason why the gimplified lhs
tree is considered is_gimple_lvalue, from:

   bool
   is_gimple_lvalue (tree t)
   {
     return (is_gimple_addressable (t)
             || TREE_CODE (t) == WITH_SIZE_EXPR
             /* These are complex lvalues, but don't have addresses, so they
                go here.  */
             || TREE_CODE (t) == BIT_FIELD_REF);

Assuming that the initial tree is valid GENERIC, it would seem that a more
sophisticated addressability checker (recursing down some inner refs and
checking DECL_BIT_FIELD on field decls in COMPONENT_REFs) might be required.

I'm unclear whether this could/should be is_gimple_addressable, as
comments from http://gcc.gnu.org/ml/gcc/2004-07/msg01255.html indicate
that it not designed for this sort of operation.

I'm pretty sure I'm missing implicit assumptions and/or bits of design
intents in various places, so would appreciate input on the case and
puzzles described above.

Thanks very much in advance for your help,

With Kind Regards,

Olivier



Reply via email to