> Jose E. Marchesi writes:
>
>>> This patch corrects bugs within the CO-RE builtin field expression
>>> related builtins.
>>> The following bugs were identified and corrected based on the expected
>>> results of bpf-next selftests testsuite.
>>> It addresses the following problems:
>>>  - Expressions with pointer dereferencing now point to the BTF structure
>>>    type, instead of the structure pointer type.
>>>  - Pointer addition to structure root is now identified and constructed
>>>    in CO-RE relocations as if it is an array access. For example,
>>>   "&(s+2)->b" generates "2:1" as an access string where "2" is
>>>   refering to the access for "s+2".
>>>
>>> gcc/ChangeLog:
>>>     * config/bpf/core-builtins.cc (core_field_info): Add
>>>     support for POINTER_PLUS_EXPR in the root of the field expression.
>>>     (bpf_core_get_index): Likewise.
>>>     (pack_field_expr): Make the BTF type to point to the structure
>>>     related node, instead of its pointer type.
>>>     (make_core_safe_access_index): Correct to new code.
>>>
>>> gcc/testsuite/ChangeLog:
>>>     * gcc.target/bpf/core-attr-5.c: Correct.
>>>     * gcc.target/bpf/core-attr-6.c: Likewise.
>>>     * gcc.target/bpf/core-attr-struct-as-array.c: Add test case for
>>>     pointer arithmetics as array access use case.
>>> ---
>>>  gcc/config/bpf/core-builtins.cc               | 54 +++++++++++++++----
>>>  gcc/testsuite/gcc.target/bpf/core-attr-5.c    |  4 +-
>>>  gcc/testsuite/gcc.target/bpf/core-attr-6.c    |  4 +-
>>>  .../bpf/core-attr-struct-as-array.c           | 35 ++++++++++++
>>>  4 files changed, 82 insertions(+), 15 deletions(-)
>>>  create mode 100644 gcc/testsuite/gcc.target/bpf/core-attr-struct-as-array.c
>>>
>>> diff --git a/gcc/config/bpf/core-builtins.cc 
>>> b/gcc/config/bpf/core-builtins.cc
>>> index 8d8c54c1fb3d..4256fea15e49 100644
>>> --- a/gcc/config/bpf/core-builtins.cc
>>> +++ b/gcc/config/bpf/core-builtins.cc
>>> @@ -388,8 +388,8 @@ core_field_info (tree src, enum btf_core_reloc_kind 
>>> kind)
>>>
>>>    src = root_for_core_field_info (src);
>>>
>>> -  get_inner_reference (src, &bitsize, &bitpos, &var_off, &mode, &unsignedp,
>>> -                  &reversep, &volatilep);
>>> +  tree root = get_inner_reference (src, &bitsize, &bitpos, &var_off, &mode,
>>> +                              &unsignedp, &reversep, &volatilep);
>>>
>>>    /* Note: Use DECL_BIT_FIELD_TYPE rather than DECL_BIT_FIELD here, 
>>> because it
>>>       remembers whether the field in question was originally declared as a
>>> @@ -414,6 +414,23 @@ core_field_info (tree src, enum btf_core_reloc_kind 
>>> kind)
>>>      {
>>>      case BPF_RELO_FIELD_BYTE_OFFSET:
>>>        {
>>> +   result = 0;
>>> +   if (var_off == NULL_TREE
>>> +       && TREE_CODE (root) == INDIRECT_REF
>>> +       && TREE_CODE (TREE_OPERAND (root, 0)) == POINTER_PLUS_EXPR)
>>> +     {
>>> +       tree node = TREE_OPERAND (root, 0);
>>> +       tree offset = TREE_OPERAND (node, 1);
>>> +       tree type = TREE_TYPE (TREE_OPERAND (node, 0));
>>> +       type = TREE_TYPE (type);
>>> +
>>> +       gcc_assert (TREE_CODE (offset) == INTEGER_CST && tree_fits_shwi_p 
>>> (offset)
>>> +           && COMPLETE_TYPE_P (type) && tree_fits_shwi_p (TYPE_SIZE 
>>> (type)));
>>
>> What if an expression with a non-constant offset (something like s+foo)
>> is passed to the builtin?  Wouldn't it be better to error there instead
>> of ICEing?
>>
> In that case, var_off == NULL_TREE, and it did not reach the assert.
> In any case, please notice that this code was copied from some different
> code in the same file which in that case would actually produce the
> error earlier.  The assert is there as a safe guard just in case the
> other function stops detecting this case.
>
> In core-builtins.cc:572
>
>     else if (code == POINTER_PLUS_EXPR)
>       {
>         tree offset = TREE_OPERAND (node, 1);
>         tree type = TREE_TYPE (TREE_OPERAND (node, 0));
>         type = TREE_TYPE (type);
>
>         if (TREE_CODE (offset) == INTEGER_CST && tree_fits_shwi_p (offset)
>             && COMPLETE_TYPE_P (type) && tree_fits_shwi_p (TYPE_SIZE (type)))
>           {
>             HOST_WIDE_INT offset_i = tree_to_shwi (offset);
>             HOST_WIDE_INT type_size_i = tree_to_shwi (TYPE_SIZE_UNIT (type));
>             if ((offset_i % type_size_i) == 0)
>               return offset_i / type_size_i;
>           }
>       }
>
>     if (valid != NULL)
>       *valid = false;
>     return -1;
>   }
>
> Because the code, although similar, is actually having different
> purposes, I decided not to abstract this in an independent function. My
> perception was that it would be more confusing.
>
> Without wanting to paste too much code, please notice that the function
> with the assert is only called if the above function, does not return
> with error (i.e. valid != false).

Ok understood.
Please submit upstream.
Thanks!

>
>>
>>> +
>>> +       HOST_WIDE_INT offset_i = tree_to_shwi (offset);
>>> +       result += offset_i;
>>> +     }
>>> +
>>>     type = unsigned_type_node;
>>>     if (var_off != NULL_TREE)
>>>       {
>>> @@ -422,9 +439,9 @@ core_field_info (tree src, enum btf_core_reloc_kind 
>>> kind)
>>>       }
>>>
>>>     if (bitfieldp)
>>> -     result = start_bitpos / 8;
>>> +     result += start_bitpos / 8;
>>>     else
>>> -     result = bitpos / 8;
>>> +     result += bitpos / 8;
>>>        }
>>>        break;
>>>
>>> @@ -552,6 +569,7 @@ bpf_core_get_index (const tree node, bool *valid)
>>>      {
>>>        tree offset = TREE_OPERAND (node, 1);
>>>        tree type = TREE_TYPE (TREE_OPERAND (node, 0));
>>> +      type = TREE_TYPE (type);
>>>
>>>        if (TREE_CODE (offset) == INTEGER_CST && tree_fits_shwi_p (offset)
>>>       && COMPLETE_TYPE_P (type) && tree_fits_shwi_p (TYPE_SIZE (type)))
>>> @@ -627,14 +645,18 @@ compute_field_expr (tree node, unsigned int 
>>> *accessors,
>>>
>>>    switch (TREE_CODE (node))
>>>      {
>>> -    case ADDR_EXPR:
>>> -      return 0;
>>>      case INDIRECT_REF:
>>> -      accessors[0] = 0;
>>> -      return 1;
>>> -    case POINTER_PLUS_EXPR:
>>> -      accessors[0] = bpf_core_get_index (node, valid);
>>> -      return 1;
>>> +      if (TREE_CODE (node = TREE_OPERAND (node, 0)) == POINTER_PLUS_EXPR)
>>> +   {
>>> +     accessors[0] = bpf_core_get_index (node, valid);
>>> +     *access_node = TREE_OPERAND (node, 0);
>>> +     return 1;
>>> +   }
>>> +      else
>>> +   {
>>> +     accessors[0] = 0;
>>> +     return 1;
>>> +   }
>>>      case COMPONENT_REF:
>>>        n = compute_field_expr (TREE_OPERAND (node, 0), accessors,
>>>                           valid,
>>> @@ -660,6 +682,7 @@ compute_field_expr (tree node, unsigned int *accessors,
>>>                           access_node, false);
>>>        return n;
>>>
>>> +    case ADDR_EXPR:
>>>      case CALL_EXPR:
>>>      case SSA_NAME:
>>>      case VAR_DECL:
>>> @@ -688,6 +711,9 @@ pack_field_expr (tree *args,
>>>    tree access_node = NULL_TREE;
>>>    tree type = NULL_TREE;
>>>
>>> +  if (TREE_CODE (root) == ADDR_EXPR)
>>> +    root = TREE_OPERAND (root, 0);
>>> +
>>>    ret.reloc_decision = REPLACE_CREATE_RELOCATION;
>>>
>>>    unsigned int accessors[100];
>>> @@ -695,6 +721,8 @@ pack_field_expr (tree *args,
>>>    compute_field_expr (root, accessors, &valid, &access_node, false);
>>>
>>>    type = TREE_TYPE (access_node);
>>> +  if (POINTER_TYPE_P (type))
>>> +    type = TREE_TYPE (type);
>>>
>>>    if (valid == true)
>>>      {
>>> @@ -1351,6 +1379,8 @@ make_core_safe_access_index (tree expr, bool 
>>> *changed, bool entry = true)
>>>    if (base == NULL_TREE || base == expr)
>>>      return expr;
>>>
>>> +  base = expr;
>>> +
>>>    tree ret = NULL_TREE;
>>>    int n;
>>>    bool valid = true;
>>> @@ -1365,6 +1395,8 @@ make_core_safe_access_index (tree expr, bool 
>>> *changed, bool entry = true)
>>>      {
>>>        if (TREE_CODE (access_node) == INDIRECT_REF)
>>>     base = TREE_OPERAND (access_node, 0);
>>> +      else
>>> +   base = access_node;
>>>
>>>        bool local_changed = false;
>>>        ret = make_core_safe_access_index (base, &local_changed, false);
>>> diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-5.c 
>>> b/gcc/testsuite/gcc.target/bpf/core-attr-5.c
>>> index e71901d0d4d1..90734dab3a29 100644
>>> --- a/gcc/testsuite/gcc.target/bpf/core-attr-5.c
>>> +++ b/gcc/testsuite/gcc.target/bpf/core-attr-5.c
>>> @@ -63,5 +63,5 @@ func (struct T *t, int i)
>>>  /* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:2\"\\)" 1 } 
>>> } */
>>>  /* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:1:1\"\\)" 1 
>>> } } */
>>>  /* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:0\"\\)" 1 } } 
>>> */
>>> -/* { dg-final { scan-assembler-times "bpfcr_type \\(struct T \\*\\)" 4 } } 
>>> */
>>> -/* { dg-final { scan-assembler-times "bpfcr_type \\(struct U \\*\\)" 4 { 
>>> xfail *-*-* } } } */
>>> +/* { dg-final { scan-assembler-times "bpfcr_type \\(struct T\\)" 4 } } */
>>> +/* { dg-final { scan-assembler-times "bpfcr_type \\(struct U\\)" 4 { xfail 
>>> *-*-* } } } */
>>> diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-6.c 
>>> b/gcc/testsuite/gcc.target/bpf/core-attr-6.c
>>> index 34a4c367e528..d0c5371b86e0 100644
>>> --- a/gcc/testsuite/gcc.target/bpf/core-attr-6.c
>>> +++ b/gcc/testsuite/gcc.target/bpf/core-attr-6.c
>>> @@ -45,6 +45,6 @@ func (struct T *t, int i)
>>>  /* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:3\"\\)" 2 } } 
>>> */
>>>  /* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1:2\"\\)" 1 } 
>>> } */
>>>  /* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:0\"\\)" 1 } } 
>>> */
>>> -/* { dg-final { scan-assembler-times "bpfcr_type \\(struct T \\*\\)" 3 } } 
>>> */
>>> -/* { dg-final { scan-assembler-times "bpfcr_type \\(struct U \\*\\)" 2 } } 
>>> */
>>> +/* { dg-final { scan-assembler-times "bpfcr_type \\(struct T\\)" 3 } } */
>>> +/* { dg-final { scan-assembler-times "bpfcr_type \\(struct U\\)" 2 } } */
>>>
>>> diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-struct-as-array.c 
>>> b/gcc/testsuite/gcc.target/bpf/core-attr-struct-as-array.c
>>> new file mode 100644
>>> index 000000000000..3f6eb9cb97f8
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.target/bpf/core-attr-struct-as-array.c
>>> @@ -0,0 +1,35 @@
>>> +/* Basic test for struct __attribute__((preserve_access_index))
>>> +   for BPF CO-RE support.  */
>>> +
>>> +/* { dg-do compile } */
>>> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
>>> +
>>> +struct S {
>>> +  int a;
>>> +  int b;
>>> +  int c;
>>> +} __attribute__((preserve_access_index));
>>> +
>>> +void
>>> +func (struct S * s)
>>> +{
>>> +  /* This test is marked as XFAIL since for the time being the CO-RE
>>> +     implementation is not able to disambiguate between a point 
>>> manipulation
>>> +     and a CO-RE access when using preserve_access_index attribute.  The
>>> +     current implemetantion is incorrect if we consider that STRUCT S might
>>> +     have different size within the kernel.
>>> +     This example demonstrates how the implementation of 
>>> preserve_access_index
>>> +     as an attribute of the type is flagile.  */
>>> +
>>> +  /* 2:2 */
>>> +  int *x = &((s+2)->c);
>>> +  *x = 4;
>>> +
>>> +  /* 2:1 */
>>> +  int *y = __builtin_preserve_access_index (&((s+2)->b));
>>> +  *y = 2;
>>> +}
>>> +
>>> +/* { dg-final { scan-assembler-times "ascii \"2:2.0\"\[\t 
>>> \]+\[^\n\]*btf_aux_string" 1 { xfail *-*-* } } } */
>>> +/* { dg-final { scan-assembler-times "ascii \"2:1.0\"\[\t 
>>> \]+\[^\n\]*btf_aux_string" 1 } } */
>>> +/* { dg-final { scan-assembler-times "bpfcr_type" 2 } } */

Reply via email to