> 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?

> +
> +         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