[2/2] bpf: CO-RE builtins support tests.
Checks
Commit Message
This patch adds tests for the following builtins:
__builtin_preserve_enum_value
__builtin_btf_type_id
__builtin_preserve_type_info
---
.../gcc.target/bpf/core-builtin-enumvalue.c | 52 +++++++++
.../bpf/core-builtin-enumvalue_errors.c | 22 ++++
.../bpf/core-builtin-enumvalue_opt.c | 35 ++++++
.../bpf/core-builtin-fieldinfo-errors-1.c | 2 +-
.../bpf/core-builtin-fieldinfo-errors-2.c | 2 +-
.../gcc.target/bpf/core-builtin-type-based.c | 58 ++++++++++
.../gcc.target/bpf/core-builtin-type-id.c | 40 +++++++
gcc/testsuite/gcc.target/bpf/core-support.h | 109 ++++++++++++++++++
8 files changed, 318 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c
create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c
create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c
create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c
create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c
create mode 100644 gcc/testsuite/gcc.target/bpf/core-support.h
Comments
Hi,
Resending this patch since I have noticed I had a testcase added in
previous patch. Makes more sense here.
Thanks,
Cupertino
OK.
Thanks.
> Hi,
>
> Resending this patch since I have noticed I had a testcase added in
> previous patch. Makes more sense here.
>
> Thanks,
> Cupertino
>
> From 334e9ae0f428f6573f2a5e8a3067a4d181b8b9c5 Mon Sep 17 00:00:00 2001
> From: Cupertino Miranda <cupertino.miranda@oracle.com>
> Date: Thu, 27 Jul 2023 18:05:22 +0100
> Subject: [PATCH v2 2/2] bpf: CO-RE builtins support tests.
>
> This patch adds tests for the following builtins:
> __builtin_preserve_enum_value
> __builtin_btf_type_id
> __builtin_preserve_type_info
> ---
> .../gcc.target/bpf/core-builtin-enumvalue.c | 52 +++++++++
> .../bpf/core-builtin-enumvalue_errors.c | 22 ++++
> .../bpf/core-builtin-enumvalue_opt.c | 35 ++++++
> ...core-builtin-fieldinfo-const-elimination.c | 29 +++++
> .../bpf/core-builtin-fieldinfo-errors-1.c | 2 +-
> .../bpf/core-builtin-fieldinfo-errors-2.c | 2 +-
> .../gcc.target/bpf/core-builtin-type-based.c | 58 ++++++++++
> .../gcc.target/bpf/core-builtin-type-id.c | 40 +++++++
> gcc/testsuite/gcc.target/bpf/core-support.h | 109 ++++++++++++++++++
> 9 files changed, 347 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c
> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c
> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c
> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c
> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c
> create mode 100644 gcc/testsuite/gcc.target/bpf/core-support.h
>
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c
> new file mode 100644
> index 000000000000..3e3334dc089a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c
> @@ -0,0 +1,52 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
> +
> +#include "core-support.h"
> +
> +extern int *v;
> +
> +int foo(void *data)
> +{
> + int i = 0;
> + enum named_ue64 named_unsigned64 = 0;
> + enum named_se64 named_signed64 = 0;
> + enum named_ue named_unsigned = 0;
> + enum named_se named_signed = 0;
> +
> + v[i++] = bpf_core_enum_value_exists (named_unsigned64, UE64_VAL1);
> + v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL2);
> + v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL3);
> + v[i++] = bpf_core_enum_value_exists (named_signed64, SE64_VAL1);
> + v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL2);
> + v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL3);
> +
> + v[i++] = bpf_core_enum_value (named_unsigned64, UE64_VAL1);
> + v[i++] = bpf_core_enum_value (named_unsigned64, UE64_VAL2);
> + v[i++] = bpf_core_enum_value (named_signed64, SE64_VAL1);
> + v[i++] = bpf_core_enum_value (named_signed64, SE64_VAL2);
> +
> + v[i++] = bpf_core_enum_value_exists (named_unsigned, UE_VAL1);
> + v[i++] = bpf_core_enum_value_exists (enum named_ue, UE_VAL2);
> + v[i++] = bpf_core_enum_value_exists (enum named_ue, UE_VAL3);
> + v[i++] = bpf_core_enum_value_exists (named_signed, SE_VAL1);
> + v[i++] = bpf_core_enum_value_exists (enum named_se, SE_VAL2);
> + v[i++] = bpf_core_enum_value_exists (enum named_se, SE_VAL3);
> +
> + v[i++] = bpf_core_enum_value (named_unsigned, UE_VAL1);
> + v[i++] = bpf_core_enum_value (named_unsigned, UE_VAL2);
> + v[i++] = bpf_core_enum_value (named_signed, SE_VAL1);
> + v[i++] = bpf_core_enum_value (named_signed, SE_VAL2);
> +
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_type \\(named_ue64\\)" 5 } } */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_type \\(named_se64\\)" 5} } */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_type \\(named_ue\\)" 5 } } */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0xc\t; bpfcr_type \\(named_se\\)" 5} } */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0xa\t; bpfcr_kind" 12 } } BPF_ENUMVAL_EXISTS */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_kind" 8 } } BPF_ENUMVAL_VALUE */
> +
> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0\"\\)" 8 } } */
> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"1\"\\)" 8 } } */
> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"2\"\\)" 4 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c
> new file mode 100644
> index 000000000000..138e99895160
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c
> @@ -0,0 +1,22 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
> +
> +#include "core-support.h"
> +
> +extern int *v;
> +
> +unsigned long foo(void *data)
> +{
> + int i = 0;
> + enum named_ue64 named_unsigned = 0;
> + enum named_se64 named_signed = 0;
> + typeof(enum named_ue64) a = 0;
> +
> + v[i++] = __builtin_preserve_enum_value (({ extern typeof(named_unsigned) *_type0; _type0; }), 0, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid enum value argument for enum value builtin" } */
> + v[i++] = __builtin_preserve_enum_value (({ extern typeof(enum named_ue64) *_type0; _type0; }), v, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid enum value argument for enum value builtin" } */
> + v[i++] = __builtin_preserve_enum_value (a, UE64_VAL3, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid type argument format for enum value builtin" } */
> + v[i++] = __builtin_preserve_enum_value (UE64_VAL3); /* { dg-error "wrong number of arguments for enum value core builtin" } */
> +
> +
> + return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c
> new file mode 100644
> index 000000000000..363ad0c41ecc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c
> @@ -0,0 +1,35 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -dA -gbtf -mco-re" } */
> +
> +#include "core-support.h"
> +
> +extern int *v;
> +
> +unsigned long foo(void *data)
> +{
> + enum named_ue64 named_unsigned = 0;
> + enum named_se64 named_signed = 0;
> + int i = 0;
> +
> + v[i++] = bpf_core_enum_value_exists (named_unsigned, UE64_VAL1);
> + v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL1);
> + v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL1);
> + v[i++] = bpf_core_enum_value_exists (named_signed, SE64_VAL1);
> + v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL1);
> + v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL1);
> +
> + v[i++] = bpf_core_enum_value (named_unsigned, UE64_VAL1);
> + v[i++] = bpf_core_enum_value (named_unsigned, UE64_VAL1);
> + v[i++] = bpf_core_enum_value (named_signed, SE64_VAL1);
> + v[i++] = bpf_core_enum_value (named_signed, SE64_VAL1);
> +
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_type \\(named_ue64\\)" 2 } } */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_type \\(named_se64\\)" 2} } */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0xa\t; bpfcr_kind" 2 } } BPF_ENUMVAL_EXISTS */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_kind" 2 } } BPF_ENUMVAL_VALUE */
> +
> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0\"\\)" 4 } } */
> +
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
> new file mode 100644
> index 000000000000..5f8354874830
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
> @@ -0,0 +1,29 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -dA -gbtf -mco-re" } */
> +
> +struct S {
> + unsigned int a1: 7;
> + unsigned int a2: 4;
> + unsigned int a3: 13;
> + unsigned int a4: 5;
> + int x;
> +};
> +
> +struct T {
> + unsigned int y;
> + struct S s[2];
> + char c;
> + char d;
> +};
> +
> +enum {
> + FIELD_BYTE_OFFSET = 0,
> +};
> +
> +unsigned int foo (struct T *t)
> +{
> + return __builtin_preserve_field_info (t->s[0].a1, FIELD_BYTE_OFFSET) + 1;
> +}
> +
> +/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 1 } } */
> +/* { dg-final { scan-assembler-times "\[\t \]add32\[\t \]%r\[0-9\],1" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c
> index 2c67c3840047..6f8c320ab8b6 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c
> @@ -17,7 +17,7 @@ unsigned int test (struct F *f) {
>
> unsigned x = __builtin_preserve_field_info (f->arr, FIELD_BYTE_SIZE); /* { dg-error "unsupported variable size field access" } */
>
> - unsigned y = __builtin_preserve_field_info (f->baz, 99); /* { dg-error "invalid second argument to built-in function" } */
> + unsigned y = __builtin_preserve_field_info (f->baz, 99); /* { dg-error "invalid kind argument to core builtin" } */
>
> return x + y;
> }
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c
> index 31d7a03b7579..08fbdf016553 100644
> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c
> @@ -17,7 +17,7 @@ int test (struct F *f) {
> unsigned x = __builtin_preserve_field_info (({ a = f->bar + f->baz; }), FIELD_BYTE_OFFSET); /* { dg-error "argument is not a field access" } */
>
> int b;
> - unsigned y = __builtin_preserve_field_info (&(f->c), FIELD_BYTE_SIZE); /* { dg-error "argument is not a field access" } */
> + unsigned y = __builtin_preserve_field_info (&(f->c), FIELD_BYTE_SIZE); /* { dg-error "argument is not a field access" "" { xfail *-*-* } } */
>
> return a + b + x + y;
> }
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c b/gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c
> new file mode 100644
> index 000000000000..16b48ae0a00d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c
> @@ -0,0 +1,58 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
> +
> +#include "core-support.h"
> +
> +extern int *v;
> +
> +int foo(void *data)
> +{
> + int i = 0;
> +
> + v[i++] = bpf_core_type_exists (struct my_struct);
> + v[i++] = bpf_core_type_exists (struct my_complex_struct);
> + v[i++] = bpf_core_type_exists (union my_union);
> + v[i++] = bpf_core_type_exists (enum my_enum);
> + v[i++] = bpf_core_type_exists (named_struct_tdef);
> + v[i++] = bpf_core_type_exists (anon_struct_tdef);
> + v[i++] = bpf_core_type_exists (struct_ptr_tdef);
> + v[i++] = bpf_core_type_exists (int_tdef);
> + v[i++] = bpf_core_type_exists (enum_tdef);
> + v[i++] = bpf_core_type_exists (void_ptr_tdef);
> + v[i++] = bpf_core_type_exists (restrict_ptr_tdef);
> + v[i++] = bpf_core_type_exists (func_tdef);
> + v[i++] = bpf_core_type_exists (array_tdef);
> +
> + v[i++] = bpf_core_type_matches (struct my_struct);
> + v[i++] = bpf_core_type_matches (struct my_complex_struct);
> + v[i++] = bpf_core_type_matches (union my_union);
> + v[i++] = bpf_core_type_matches (enum my_enum);
> + v[i++] = bpf_core_type_matches (named_struct_tdef);
> + v[i++] = bpf_core_type_matches (anon_struct_tdef);
> + v[i++] = bpf_core_type_matches (struct_ptr_tdef);
> + v[i++] = bpf_core_type_matches (int_tdef);
> + v[i++] = bpf_core_type_matches (enum_tdef);
> + v[i++] = bpf_core_type_matches (void_ptr_tdef);
> + v[i++] = bpf_core_type_matches (restrict_ptr_tdef);
> + v[i++] = bpf_core_type_matches (func_tdef);
> + v[i++] = bpf_core_type_matches (array_tdef);
> +
> + v[i++] = bpf_core_type_size (struct my_struct);
> + v[i++] = bpf_core_type_size (union my_union);
> + v[i++] = bpf_core_type_size (enum my_enum);
> + v[i++] = bpf_core_type_size (named_struct_tdef);
> + v[i++] = bpf_core_type_size (anon_struct_tdef);
> + v[i++] = bpf_core_type_size (struct_ptr_tdef);
> + v[i++] = bpf_core_type_size (int_tdef);
> + v[i++] = bpf_core_type_size (enum_tdef);
> + v[i++] = bpf_core_type_size (void_ptr_tdef);
> + v[i++] = bpf_core_type_size (func_tdef);
> + v[i++] = bpf_core_type_size (array_tdef);
> +
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x0\t; bpfcr_type" 0 } } */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_kind" 13 } } BPF_TYPE_EXISTS */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_kind" 11 } } BPF_TYPE_SIZE */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0xc\t; bpfcr_kind" 13 } } BPF_TYPE_MATCHES */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c b/gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c
> new file mode 100644
> index 000000000000..615bbc85a22c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c
> @@ -0,0 +1,40 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
> +
> +#include "core-support.h"
> +
> +extern int *v;
> +
> +int foo(void *data)
> +{
> + int i = 0;
> +
> + v[i++] = bpf_core_type_id_local (struct { int a; });
> + v[i++] = bpf_core_type_id_local (union { int a; });
> + v[i++] = bpf_core_type_id_local (enum { A = 1 });
> + v[i++] = bpf_core_type_id_local (char(*)(int));
> + v[i++] = bpf_core_type_id_local (void *);
> + v[i++] = bpf_core_type_id_local (char[10]);
> +
> + v[i++] = bpf_core_type_id_local (struct my_struct);
> + v[i++] = bpf_core_type_id_local (union my_union);
> + v[i++] = bpf_core_type_id_local (enum my_enum);
> + v[i++] = bpf_core_type_id_local (int);
> + v[i++] = bpf_core_type_id_local (named_struct_tdef);
> + v[i++] = bpf_core_type_id_local (func_tdef);
> + v[i++] = bpf_core_type_id_local (array_tdef);
> +
> + v[i++] = bpf_core_type_id_target (struct my_struct);
> + v[i++] = bpf_core_type_id_target (union my_union);
> + v[i++] = bpf_core_type_id_target (enum my_enum);
> + v[i++] = bpf_core_type_id_target (int);
> + v[i++] = bpf_core_type_id_target (named_struct_tdef);
> + v[i++] = bpf_core_type_id_target (func_tdef);
> + v[i++] = bpf_core_type_id_target (array_tdef);
> +
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times "\t.4byte\t0\t; bpfcr_type" 0 { xfail *-*-* } } } */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x6\t; bpfcr_kind" 13 } } BPF_TYPE_ID_LOCAL */
> +/* { dg-final { scan-assembler-times "\t.4byte\t0x7\t; bpfcr_kind" 7 } } BPF_TYPE_ID_TARGET */
> diff --git a/gcc/testsuite/gcc.target/bpf/core-support.h b/gcc/testsuite/gcc.target/bpf/core-support.h
> new file mode 100644
> index 000000000000..e030aa5ebf84
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/bpf/core-support.h
> @@ -0,0 +1,109 @@
> +struct my_struct {
> + int a;
> +};
> +
> +union my_union {
> + int b;
> + int c;
> +};
> +
> +typedef struct my_struct named_struct_tdef;
> +typedef int (*func_tdef)(void *);
> +
> +typedef struct {
> + int d, e;
> +} *tdef_struct_ptr;
> +
> +enum my_enum {
> + MY_ENUM_VAL1 = 1,
> + MY_ENUM_VAL2 = 2,
> +};
> +typedef enum { TE1, TE2, TE3 } enum_tdef;
> +
> +typedef int int_tdef;
> +typedef void *void_ptr_tdef;
> +typedef int *restrict restrict_ptr_tdef;
> +typedef int (*func_tdef)(void *);
> +typedef char array_tdef[10];
> +
> +struct my_complex_struct {
> + int a;
> + int b;
> + union {
> + int *a;
> + struct my_struct *s;
> + } c;
> +};
> +
> +typedef struct {
> + int a;
> +} anon_struct_tdef;
> +
> +typedef struct my_struct *struct_ptr_tdef;
> +
> +enum named_ue64 {
> + UE64_VAL1 = 0x1ffffffffULL,
> + UE64_VAL2 = 0x01fffffffULL,
> + UE64_VAL3 = 0x001ffffffULL,
> +};
> +
> +enum named_se64 {
> + SE64_VAL1 = 0x1ffffffffLL,
> + SE64_VAL2 = 0x01fffffffLL,
> + SE64_VAL3 = -1,
> +};
> +
> +enum named_ue {
> + UE_VAL1 = 0x1ffffff,
> + UE_VAL2 = 0x01fffff,
> + UE_VAL3 = 0x001ffff,
> +};
> +
> +enum named_se {
> + SE_VAL1 = 0x1fffffff,
> + SE_VAL2 = 0x01ffffff,
> + SE_VAL3 = -1,
> +};
> +
> +
> +/* BPF specific code */
> +
> +enum bpf_type_id_kind {
> + BPF_TYPE_ID_LOCAL = 0,
> + BPF_TYPE_ID_TARGET = 1,
> +};
> +
> +enum bpf_type_info_kind {
> + BPF_TYPE_EXISTS = 0,
> + BPF_TYPE_SIZE = 1,
> + BPF_TYPE_MATCHES = 2,
> +};
> +
> +enum bpf_enum_value_kind {
> + BPF_ENUMVAL_EXISTS = 0,
> + BPF_ENUMVAL_VALUE = 1,
> +};
> +
> +#define COMPOSE_VAR(t,s) t##s
> +#define bpf_type1(type, NR) ({ \
> + extern typeof(type) *COMPOSE_VAR(bpf_type_tmp_, NR); \
> + COMPOSE_VAR(bpf_type_tmp_, NR); \
> +})
> +#define bpf_type(type) bpf_type1(type, __COUNTER__)
> +
> +#define bpf_core_type_id_local(type) \
> + __builtin_btf_type_id(*bpf_type(type), BPF_TYPE_ID_LOCAL)
> +#define bpf_core_type_id_target(type) \
> + __builtin_btf_type_id(*bpf_type(type), BPF_TYPE_ID_TARGET)
> +
> +#define bpf_core_type_exists(type) \
> + __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_EXISTS)
> +#define bpf_core_type_matches(type) \
> + __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_MATCHES)
> +#define bpf_core_type_size(type) \
> + __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_SIZE)
> +
> +#define bpf_core_enum_value_exists(enum_type, enum_value) \
> + __builtin_preserve_enum_value(bpf_type(enum_type), enum_value, BPF_ENUMVAL_EXISTS)
> +#define bpf_core_enum_value(enum_type, enum_value) \
> + __builtin_preserve_enum_value(bpf_type(enum_type), enum_value, BPF_ENUMVAL_VALUE)
Pushed to upstream master.
Thanks !
Jose E. Marchesi writes:
> OK.
> Thanks.
>
>> Hi,
>>
>> Resending this patch since I have noticed I had a testcase added in
>> previous patch. Makes more sense here.
>>
>> Thanks,
>> Cupertino
>>
>> From 334e9ae0f428f6573f2a5e8a3067a4d181b8b9c5 Mon Sep 17 00:00:00 2001
>> From: Cupertino Miranda <cupertino.miranda@oracle.com>
>> Date: Thu, 27 Jul 2023 18:05:22 +0100
>> Subject: [PATCH v2 2/2] bpf: CO-RE builtins support tests.
>>
>> This patch adds tests for the following builtins:
>> __builtin_preserve_enum_value
>> __builtin_btf_type_id
>> __builtin_preserve_type_info
>> ---
>> .../gcc.target/bpf/core-builtin-enumvalue.c | 52 +++++++++
>> .../bpf/core-builtin-enumvalue_errors.c | 22 ++++
>> .../bpf/core-builtin-enumvalue_opt.c | 35 ++++++
>> ...core-builtin-fieldinfo-const-elimination.c | 29 +++++
>> .../bpf/core-builtin-fieldinfo-errors-1.c | 2 +-
>> .../bpf/core-builtin-fieldinfo-errors-2.c | 2 +-
>> .../gcc.target/bpf/core-builtin-type-based.c | 58 ++++++++++
>> .../gcc.target/bpf/core-builtin-type-id.c | 40 +++++++
>> gcc/testsuite/gcc.target/bpf/core-support.h | 109 ++++++++++++++++++
>> 9 files changed, 347 insertions(+), 2 deletions(-)
>> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c
>> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c
>> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c
>> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
>> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c
>> create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c
>> create mode 100644 gcc/testsuite/gcc.target/bpf/core-support.h
>>
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c
>> new file mode 100644
>> index 000000000000..3e3334dc089a
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue.c
>> @@ -0,0 +1,52 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
>> +
>> +#include "core-support.h"
>> +
>> +extern int *v;
>> +
>> +int foo(void *data)
>> +{
>> + int i = 0;
>> + enum named_ue64 named_unsigned64 = 0;
>> + enum named_se64 named_signed64 = 0;
>> + enum named_ue named_unsigned = 0;
>> + enum named_se named_signed = 0;
>> +
>> + v[i++] = bpf_core_enum_value_exists (named_unsigned64, UE64_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL2);
>> + v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL3);
>> + v[i++] = bpf_core_enum_value_exists (named_signed64, SE64_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL2);
>> + v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL3);
>> +
>> + v[i++] = bpf_core_enum_value (named_unsigned64, UE64_VAL1);
>> + v[i++] = bpf_core_enum_value (named_unsigned64, UE64_VAL2);
>> + v[i++] = bpf_core_enum_value (named_signed64, SE64_VAL1);
>> + v[i++] = bpf_core_enum_value (named_signed64, SE64_VAL2);
>> +
>> + v[i++] = bpf_core_enum_value_exists (named_unsigned, UE_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (enum named_ue, UE_VAL2);
>> + v[i++] = bpf_core_enum_value_exists (enum named_ue, UE_VAL3);
>> + v[i++] = bpf_core_enum_value_exists (named_signed, SE_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (enum named_se, SE_VAL2);
>> + v[i++] = bpf_core_enum_value_exists (enum named_se, SE_VAL3);
>> +
>> + v[i++] = bpf_core_enum_value (named_unsigned, UE_VAL1);
>> + v[i++] = bpf_core_enum_value (named_unsigned, UE_VAL2);
>> + v[i++] = bpf_core_enum_value (named_signed, SE_VAL1);
>> + v[i++] = bpf_core_enum_value (named_signed, SE_VAL2);
>> +
>> + return 0;
>> +}
>> +
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_type \\(named_ue64\\)" 5 } } */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_type \\(named_se64\\)" 5} } */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_type \\(named_ue\\)" 5 } } */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0xc\t; bpfcr_type \\(named_se\\)" 5} } */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0xa\t; bpfcr_kind" 12 } } BPF_ENUMVAL_EXISTS */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_kind" 8 } } BPF_ENUMVAL_VALUE */
>> +
>> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0\"\\)" 8 } } */
>> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"1\"\\)" 8 } } */
>> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"2\"\\)" 4 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c
>> new file mode 100644
>> index 000000000000..138e99895160
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_errors.c
>> @@ -0,0 +1,22 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
>> +
>> +#include "core-support.h"
>> +
>> +extern int *v;
>> +
>> +unsigned long foo(void *data)
>> +{
>> + int i = 0;
>> + enum named_ue64 named_unsigned = 0;
>> + enum named_se64 named_signed = 0;
>> + typeof(enum named_ue64) a = 0;
>> +
>> + v[i++] = __builtin_preserve_enum_value (({ extern typeof(named_unsigned) *_type0; _type0; }), 0, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid enum value argument for enum value builtin" } */
>> + v[i++] = __builtin_preserve_enum_value (({ extern typeof(enum named_ue64) *_type0; _type0; }), v, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid enum value argument for enum value builtin" } */
>> + v[i++] = __builtin_preserve_enum_value (a, UE64_VAL3, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid type argument format for enum value builtin" } */
>> + v[i++] = __builtin_preserve_enum_value (UE64_VAL3); /* { dg-error "wrong number of arguments for enum value core builtin" } */
>> +
>> +
>> + return 0;
>> +}
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c
>> new file mode 100644
>> index 000000000000..363ad0c41ecc
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-enumvalue_opt.c
>> @@ -0,0 +1,35 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -dA -gbtf -mco-re" } */
>> +
>> +#include "core-support.h"
>> +
>> +extern int *v;
>> +
>> +unsigned long foo(void *data)
>> +{
>> + enum named_ue64 named_unsigned = 0;
>> + enum named_se64 named_signed = 0;
>> + int i = 0;
>> +
>> + v[i++] = bpf_core_enum_value_exists (named_unsigned, UE64_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (named_signed, SE64_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL1);
>> + v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL1);
>> +
>> + v[i++] = bpf_core_enum_value (named_unsigned, UE64_VAL1);
>> + v[i++] = bpf_core_enum_value (named_unsigned, UE64_VAL1);
>> + v[i++] = bpf_core_enum_value (named_signed, SE64_VAL1);
>> + v[i++] = bpf_core_enum_value (named_signed, SE64_VAL1);
>> +
>> + return 0;
>> +}
>> +
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_type \\(named_ue64\\)" 2 } } */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_type \\(named_se64\\)" 2} } */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0xa\t; bpfcr_kind" 2 } } BPF_ENUMVAL_EXISTS */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_kind" 2 } } BPF_ENUMVAL_VALUE */
>> +
>> +/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0\"\\)" 4 } } */
>> +
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
>> new file mode 100644
>> index 000000000000..5f8354874830
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-const-elimination.c
>> @@ -0,0 +1,29 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -dA -gbtf -mco-re" } */
>> +
>> +struct S {
>> + unsigned int a1: 7;
>> + unsigned int a2: 4;
>> + unsigned int a3: 13;
>> + unsigned int a4: 5;
>> + int x;
>> +};
>> +
>> +struct T {
>> + unsigned int y;
>> + struct S s[2];
>> + char c;
>> + char d;
>> +};
>> +
>> +enum {
>> + FIELD_BYTE_OFFSET = 0,
>> +};
>> +
>> +unsigned int foo (struct T *t)
>> +{
>> + return __builtin_preserve_field_info (t->s[0].a1, FIELD_BYTE_OFFSET) + 1;
>> +}
>> +
>> +/* { dg-final { scan-assembler-times "\[\t \]mov\[\t \]%r\[0-9\],4" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]add32\[\t \]%r\[0-9\],1" 1 } } */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c
>> index 2c67c3840047..6f8c320ab8b6 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-1.c
>> @@ -17,7 +17,7 @@ unsigned int test (struct F *f) {
>>
>> unsigned x = __builtin_preserve_field_info (f->arr, FIELD_BYTE_SIZE); /* { dg-error "unsupported variable size field access" } */
>>
>> - unsigned y = __builtin_preserve_field_info (f->baz, 99); /* { dg-error "invalid second argument to built-in function" } */
>> + unsigned y = __builtin_preserve_field_info (f->baz, 99); /* { dg-error "invalid kind argument to core builtin" } */
>>
>> return x + y;
>> }
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c
>> index 31d7a03b7579..08fbdf016553 100644
>> --- a/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-errors-2.c
>> @@ -17,7 +17,7 @@ int test (struct F *f) {
>> unsigned x = __builtin_preserve_field_info (({ a = f->bar + f->baz; }), FIELD_BYTE_OFFSET); /* { dg-error "argument is not a field access" } */
>>
>> int b;
>> - unsigned y = __builtin_preserve_field_info (&(f->c), FIELD_BYTE_SIZE); /* { dg-error "argument is not a field access" } */
>> + unsigned y = __builtin_preserve_field_info (&(f->c), FIELD_BYTE_SIZE); /* { dg-error "argument is not a field access" "" { xfail *-*-* } } */
>>
>> return a + b + x + y;
>> }
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c b/gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c
>> new file mode 100644
>> index 000000000000..16b48ae0a00d
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-type-based.c
>> @@ -0,0 +1,58 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
>> +
>> +#include "core-support.h"
>> +
>> +extern int *v;
>> +
>> +int foo(void *data)
>> +{
>> + int i = 0;
>> +
>> + v[i++] = bpf_core_type_exists (struct my_struct);
>> + v[i++] = bpf_core_type_exists (struct my_complex_struct);
>> + v[i++] = bpf_core_type_exists (union my_union);
>> + v[i++] = bpf_core_type_exists (enum my_enum);
>> + v[i++] = bpf_core_type_exists (named_struct_tdef);
>> + v[i++] = bpf_core_type_exists (anon_struct_tdef);
>> + v[i++] = bpf_core_type_exists (struct_ptr_tdef);
>> + v[i++] = bpf_core_type_exists (int_tdef);
>> + v[i++] = bpf_core_type_exists (enum_tdef);
>> + v[i++] = bpf_core_type_exists (void_ptr_tdef);
>> + v[i++] = bpf_core_type_exists (restrict_ptr_tdef);
>> + v[i++] = bpf_core_type_exists (func_tdef);
>> + v[i++] = bpf_core_type_exists (array_tdef);
>> +
>> + v[i++] = bpf_core_type_matches (struct my_struct);
>> + v[i++] = bpf_core_type_matches (struct my_complex_struct);
>> + v[i++] = bpf_core_type_matches (union my_union);
>> + v[i++] = bpf_core_type_matches (enum my_enum);
>> + v[i++] = bpf_core_type_matches (named_struct_tdef);
>> + v[i++] = bpf_core_type_matches (anon_struct_tdef);
>> + v[i++] = bpf_core_type_matches (struct_ptr_tdef);
>> + v[i++] = bpf_core_type_matches (int_tdef);
>> + v[i++] = bpf_core_type_matches (enum_tdef);
>> + v[i++] = bpf_core_type_matches (void_ptr_tdef);
>> + v[i++] = bpf_core_type_matches (restrict_ptr_tdef);
>> + v[i++] = bpf_core_type_matches (func_tdef);
>> + v[i++] = bpf_core_type_matches (array_tdef);
>> +
>> + v[i++] = bpf_core_type_size (struct my_struct);
>> + v[i++] = bpf_core_type_size (union my_union);
>> + v[i++] = bpf_core_type_size (enum my_enum);
>> + v[i++] = bpf_core_type_size (named_struct_tdef);
>> + v[i++] = bpf_core_type_size (anon_struct_tdef);
>> + v[i++] = bpf_core_type_size (struct_ptr_tdef);
>> + v[i++] = bpf_core_type_size (int_tdef);
>> + v[i++] = bpf_core_type_size (enum_tdef);
>> + v[i++] = bpf_core_type_size (void_ptr_tdef);
>> + v[i++] = bpf_core_type_size (func_tdef);
>> + v[i++] = bpf_core_type_size (array_tdef);
>> +
>> + return 0;
>> +}
>> +
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x0\t; bpfcr_type" 0 } } */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_kind" 13 } } BPF_TYPE_EXISTS */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_kind" 11 } } BPF_TYPE_SIZE */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0xc\t; bpfcr_kind" 13 } } BPF_TYPE_MATCHES */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c b/gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c
>> new file mode 100644
>> index 000000000000..615bbc85a22c
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/bpf/core-builtin-type-id.c
>> @@ -0,0 +1,40 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O0 -dA -gbtf -mco-re" } */
>> +
>> +#include "core-support.h"
>> +
>> +extern int *v;
>> +
>> +int foo(void *data)
>> +{
>> + int i = 0;
>> +
>> + v[i++] = bpf_core_type_id_local (struct { int a; });
>> + v[i++] = bpf_core_type_id_local (union { int a; });
>> + v[i++] = bpf_core_type_id_local (enum { A = 1 });
>> + v[i++] = bpf_core_type_id_local (char(*)(int));
>> + v[i++] = bpf_core_type_id_local (void *);
>> + v[i++] = bpf_core_type_id_local (char[10]);
>> +
>> + v[i++] = bpf_core_type_id_local (struct my_struct);
>> + v[i++] = bpf_core_type_id_local (union my_union);
>> + v[i++] = bpf_core_type_id_local (enum my_enum);
>> + v[i++] = bpf_core_type_id_local (int);
>> + v[i++] = bpf_core_type_id_local (named_struct_tdef);
>> + v[i++] = bpf_core_type_id_local (func_tdef);
>> + v[i++] = bpf_core_type_id_local (array_tdef);
>> +
>> + v[i++] = bpf_core_type_id_target (struct my_struct);
>> + v[i++] = bpf_core_type_id_target (union my_union);
>> + v[i++] = bpf_core_type_id_target (enum my_enum);
>> + v[i++] = bpf_core_type_id_target (int);
>> + v[i++] = bpf_core_type_id_target (named_struct_tdef);
>> + v[i++] = bpf_core_type_id_target (func_tdef);
>> + v[i++] = bpf_core_type_id_target (array_tdef);
>> +
>> + return 0;
>> +}
>> +
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0\t; bpfcr_type" 0 { xfail *-*-* } } } */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x6\t; bpfcr_kind" 13 } } BPF_TYPE_ID_LOCAL */
>> +/* { dg-final { scan-assembler-times "\t.4byte\t0x7\t; bpfcr_kind" 7 } } BPF_TYPE_ID_TARGET */
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-support.h b/gcc/testsuite/gcc.target/bpf/core-support.h
>> new file mode 100644
>> index 000000000000..e030aa5ebf84
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/bpf/core-support.h
>> @@ -0,0 +1,109 @@
>> +struct my_struct {
>> + int a;
>> +};
>> +
>> +union my_union {
>> + int b;
>> + int c;
>> +};
>> +
>> +typedef struct my_struct named_struct_tdef;
>> +typedef int (*func_tdef)(void *);
>> +
>> +typedef struct {
>> + int d, e;
>> +} *tdef_struct_ptr;
>> +
>> +enum my_enum {
>> + MY_ENUM_VAL1 = 1,
>> + MY_ENUM_VAL2 = 2,
>> +};
>> +typedef enum { TE1, TE2, TE3 } enum_tdef;
>> +
>> +typedef int int_tdef;
>> +typedef void *void_ptr_tdef;
>> +typedef int *restrict restrict_ptr_tdef;
>> +typedef int (*func_tdef)(void *);
>> +typedef char array_tdef[10];
>> +
>> +struct my_complex_struct {
>> + int a;
>> + int b;
>> + union {
>> + int *a;
>> + struct my_struct *s;
>> + } c;
>> +};
>> +
>> +typedef struct {
>> + int a;
>> +} anon_struct_tdef;
>> +
>> +typedef struct my_struct *struct_ptr_tdef;
>> +
>> +enum named_ue64 {
>> + UE64_VAL1 = 0x1ffffffffULL,
>> + UE64_VAL2 = 0x01fffffffULL,
>> + UE64_VAL3 = 0x001ffffffULL,
>> +};
>> +
>> +enum named_se64 {
>> + SE64_VAL1 = 0x1ffffffffLL,
>> + SE64_VAL2 = 0x01fffffffLL,
>> + SE64_VAL3 = -1,
>> +};
>> +
>> +enum named_ue {
>> + UE_VAL1 = 0x1ffffff,
>> + UE_VAL2 = 0x01fffff,
>> + UE_VAL3 = 0x001ffff,
>> +};
>> +
>> +enum named_se {
>> + SE_VAL1 = 0x1fffffff,
>> + SE_VAL2 = 0x01ffffff,
>> + SE_VAL3 = -1,
>> +};
>> +
>> +
>> +/* BPF specific code */
>> +
>> +enum bpf_type_id_kind {
>> + BPF_TYPE_ID_LOCAL = 0,
>> + BPF_TYPE_ID_TARGET = 1,
>> +};
>> +
>> +enum bpf_type_info_kind {
>> + BPF_TYPE_EXISTS = 0,
>> + BPF_TYPE_SIZE = 1,
>> + BPF_TYPE_MATCHES = 2,
>> +};
>> +
>> +enum bpf_enum_value_kind {
>> + BPF_ENUMVAL_EXISTS = 0,
>> + BPF_ENUMVAL_VALUE = 1,
>> +};
>> +
>> +#define COMPOSE_VAR(t,s) t##s
>> +#define bpf_type1(type, NR) ({ \
>> + extern typeof(type) *COMPOSE_VAR(bpf_type_tmp_, NR); \
>> + COMPOSE_VAR(bpf_type_tmp_, NR); \
>> +})
>> +#define bpf_type(type) bpf_type1(type, __COUNTER__)
>> +
>> +#define bpf_core_type_id_local(type) \
>> + __builtin_btf_type_id(*bpf_type(type), BPF_TYPE_ID_LOCAL)
>> +#define bpf_core_type_id_target(type) \
>> + __builtin_btf_type_id(*bpf_type(type), BPF_TYPE_ID_TARGET)
>> +
>> +#define bpf_core_type_exists(type) \
>> + __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_EXISTS)
>> +#define bpf_core_type_matches(type) \
>> + __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_MATCHES)
>> +#define bpf_core_type_size(type) \
>> + __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_SIZE)
>> +
>> +#define bpf_core_enum_value_exists(enum_type, enum_value) \
>> + __builtin_preserve_enum_value(bpf_type(enum_type), enum_value, BPF_ENUMVAL_EXISTS)
>> +#define bpf_core_enum_value(enum_type, enum_value) \
>> + __builtin_preserve_enum_value(bpf_type(enum_type), enum_value, BPF_ENUMVAL_VALUE)
new file mode 100644
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+#include "core-support.h"
+
+extern int *v;
+
+int foo(void *data)
+{
+ int i = 0;
+ enum named_ue64 named_unsigned64 = 0;
+ enum named_se64 named_signed64 = 0;
+ enum named_ue named_unsigned = 0;
+ enum named_se named_signed = 0;
+
+ v[i++] = bpf_core_enum_value_exists (named_unsigned64, UE64_VAL1);
+ v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL2);
+ v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL3);
+ v[i++] = bpf_core_enum_value_exists (named_signed64, SE64_VAL1);
+ v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL2);
+ v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL3);
+
+ v[i++] = bpf_core_enum_value (named_unsigned64, UE64_VAL1);
+ v[i++] = bpf_core_enum_value (named_unsigned64, UE64_VAL2);
+ v[i++] = bpf_core_enum_value (named_signed64, SE64_VAL1);
+ v[i++] = bpf_core_enum_value (named_signed64, SE64_VAL2);
+
+ v[i++] = bpf_core_enum_value_exists (named_unsigned, UE_VAL1);
+ v[i++] = bpf_core_enum_value_exists (enum named_ue, UE_VAL2);
+ v[i++] = bpf_core_enum_value_exists (enum named_ue, UE_VAL3);
+ v[i++] = bpf_core_enum_value_exists (named_signed, SE_VAL1);
+ v[i++] = bpf_core_enum_value_exists (enum named_se, SE_VAL2);
+ v[i++] = bpf_core_enum_value_exists (enum named_se, SE_VAL3);
+
+ v[i++] = bpf_core_enum_value (named_unsigned, UE_VAL1);
+ v[i++] = bpf_core_enum_value (named_unsigned, UE_VAL2);
+ v[i++] = bpf_core_enum_value (named_signed, SE_VAL1);
+ v[i++] = bpf_core_enum_value (named_signed, SE_VAL2);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_type \\(named_ue64\\)" 5 } } */
+/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_type \\(named_se64\\)" 5} } */
+/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_type \\(named_ue\\)" 5 } } */
+/* { dg-final { scan-assembler-times "\t.4byte\t0xc\t; bpfcr_type \\(named_se\\)" 5} } */
+/* { dg-final { scan-assembler-times "\t.4byte\t0xa\t; bpfcr_kind" 12 } } BPF_ENUMVAL_EXISTS */
+/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_kind" 8 } } BPF_ENUMVAL_VALUE */
+
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0\"\\)" 8 } } */
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"1\"\\)" 8 } } */
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"2\"\\)" 4 } } */
new file mode 100644
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+#include "core-support.h"
+
+extern int *v;
+
+unsigned long foo(void *data)
+{
+ int i = 0;
+ enum named_ue64 named_unsigned = 0;
+ enum named_se64 named_signed = 0;
+ typeof(enum named_ue64) a = 0;
+
+ v[i++] = __builtin_preserve_enum_value (({ extern typeof(named_unsigned) *_type0; _type0; }), 0, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid enum value argument for enum value builtin" } */
+ v[i++] = __builtin_preserve_enum_value (({ extern typeof(enum named_ue64) *_type0; _type0; }), v, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid enum value argument for enum value builtin" } */
+ v[i++] = __builtin_preserve_enum_value (a, UE64_VAL3, BPF_ENUMVAL_EXISTS); /* { dg-error "invalid type argument format for enum value builtin" } */
+ v[i++] = __builtin_preserve_enum_value (UE64_VAL3); /* { dg-error "wrong number of arguments for enum value core builtin" } */
+
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -dA -gbtf -mco-re" } */
+
+#include "core-support.h"
+
+extern int *v;
+
+unsigned long foo(void *data)
+{
+ enum named_ue64 named_unsigned = 0;
+ enum named_se64 named_signed = 0;
+ int i = 0;
+
+ v[i++] = bpf_core_enum_value_exists (named_unsigned, UE64_VAL1);
+ v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL1);
+ v[i++] = bpf_core_enum_value_exists (enum named_ue64, UE64_VAL1);
+ v[i++] = bpf_core_enum_value_exists (named_signed, SE64_VAL1);
+ v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL1);
+ v[i++] = bpf_core_enum_value_exists (enum named_se64, SE64_VAL1);
+
+ v[i++] = bpf_core_enum_value (named_unsigned, UE64_VAL1);
+ v[i++] = bpf_core_enum_value (named_unsigned, UE64_VAL1);
+ v[i++] = bpf_core_enum_value (named_signed, SE64_VAL1);
+ v[i++] = bpf_core_enum_value (named_signed, SE64_VAL1);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_type \\(named_ue64\\)" 2 } } */
+/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_type \\(named_se64\\)" 2} } */
+/* { dg-final { scan-assembler-times "\t.4byte\t0xa\t; bpfcr_kind" 2 } } BPF_ENUMVAL_EXISTS */
+/* { dg-final { scan-assembler-times "\t.4byte\t0xb\t; bpfcr_kind" 2 } } BPF_ENUMVAL_VALUE */
+
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0\"\\)" 4 } } */
+
@@ -17,7 +17,7 @@ unsigned int test (struct F *f) {
unsigned x = __builtin_preserve_field_info (f->arr, FIELD_BYTE_SIZE); /* { dg-error "unsupported variable size field access" } */
- unsigned y = __builtin_preserve_field_info (f->baz, 99); /* { dg-error "invalid second argument to built-in function" } */
+ unsigned y = __builtin_preserve_field_info (f->baz, 99); /* { dg-error "invalid kind argument to core builtin" } */
return x + y;
}
@@ -17,7 +17,7 @@ int test (struct F *f) {
unsigned x = __builtin_preserve_field_info (({ a = f->bar + f->baz; }), FIELD_BYTE_OFFSET); /* { dg-error "argument is not a field access" } */
int b;
- unsigned y = __builtin_preserve_field_info (&(f->c), FIELD_BYTE_SIZE); /* { dg-error "argument is not a field access" } */
+ unsigned y = __builtin_preserve_field_info (&(f->c), FIELD_BYTE_SIZE); /* { dg-error "argument is not a field access" "" { xfail *-*-* } } */
return a + b + x + y;
}
new file mode 100644
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+#include "core-support.h"
+
+extern int *v;
+
+int foo(void *data)
+{
+ int i = 0;
+
+ v[i++] = bpf_core_type_exists (struct my_struct);
+ v[i++] = bpf_core_type_exists (struct my_complex_struct);
+ v[i++] = bpf_core_type_exists (union my_union);
+ v[i++] = bpf_core_type_exists (enum my_enum);
+ v[i++] = bpf_core_type_exists (named_struct_tdef);
+ v[i++] = bpf_core_type_exists (anon_struct_tdef);
+ v[i++] = bpf_core_type_exists (struct_ptr_tdef);
+ v[i++] = bpf_core_type_exists (int_tdef);
+ v[i++] = bpf_core_type_exists (enum_tdef);
+ v[i++] = bpf_core_type_exists (void_ptr_tdef);
+ v[i++] = bpf_core_type_exists (restrict_ptr_tdef);
+ v[i++] = bpf_core_type_exists (func_tdef);
+ v[i++] = bpf_core_type_exists (array_tdef);
+
+ v[i++] = bpf_core_type_matches (struct my_struct);
+ v[i++] = bpf_core_type_matches (struct my_complex_struct);
+ v[i++] = bpf_core_type_matches (union my_union);
+ v[i++] = bpf_core_type_matches (enum my_enum);
+ v[i++] = bpf_core_type_matches (named_struct_tdef);
+ v[i++] = bpf_core_type_matches (anon_struct_tdef);
+ v[i++] = bpf_core_type_matches (struct_ptr_tdef);
+ v[i++] = bpf_core_type_matches (int_tdef);
+ v[i++] = bpf_core_type_matches (enum_tdef);
+ v[i++] = bpf_core_type_matches (void_ptr_tdef);
+ v[i++] = bpf_core_type_matches (restrict_ptr_tdef);
+ v[i++] = bpf_core_type_matches (func_tdef);
+ v[i++] = bpf_core_type_matches (array_tdef);
+
+ v[i++] = bpf_core_type_size (struct my_struct);
+ v[i++] = bpf_core_type_size (union my_union);
+ v[i++] = bpf_core_type_size (enum my_enum);
+ v[i++] = bpf_core_type_size (named_struct_tdef);
+ v[i++] = bpf_core_type_size (anon_struct_tdef);
+ v[i++] = bpf_core_type_size (struct_ptr_tdef);
+ v[i++] = bpf_core_type_size (int_tdef);
+ v[i++] = bpf_core_type_size (enum_tdef);
+ v[i++] = bpf_core_type_size (void_ptr_tdef);
+ v[i++] = bpf_core_type_size (func_tdef);
+ v[i++] = bpf_core_type_size (array_tdef);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "\t.4byte\t0x0\t; bpfcr_type" 0 } } */
+/* { dg-final { scan-assembler-times "\t.4byte\t0x8\t; bpfcr_kind" 13 } } BPF_TYPE_EXISTS */
+/* { dg-final { scan-assembler-times "\t.4byte\t0x9\t; bpfcr_kind" 11 } } BPF_TYPE_SIZE */
+/* { dg-final { scan-assembler-times "\t.4byte\t0xc\t; bpfcr_kind" 13 } } BPF_TYPE_MATCHES */
new file mode 100644
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -dA -gbtf -mco-re" } */
+
+#include "core-support.h"
+
+extern int *v;
+
+int foo(void *data)
+{
+ int i = 0;
+
+ v[i++] = bpf_core_type_id_local (struct { int a; });
+ v[i++] = bpf_core_type_id_local (union { int a; });
+ v[i++] = bpf_core_type_id_local (enum { A = 1 });
+ v[i++] = bpf_core_type_id_local (char(*)(int));
+ v[i++] = bpf_core_type_id_local (void *);
+ v[i++] = bpf_core_type_id_local (char[10]);
+
+ v[i++] = bpf_core_type_id_local (struct my_struct);
+ v[i++] = bpf_core_type_id_local (union my_union);
+ v[i++] = bpf_core_type_id_local (enum my_enum);
+ v[i++] = bpf_core_type_id_local (int);
+ v[i++] = bpf_core_type_id_local (named_struct_tdef);
+ v[i++] = bpf_core_type_id_local (func_tdef);
+ v[i++] = bpf_core_type_id_local (array_tdef);
+
+ v[i++] = bpf_core_type_id_target (struct my_struct);
+ v[i++] = bpf_core_type_id_target (union my_union);
+ v[i++] = bpf_core_type_id_target (enum my_enum);
+ v[i++] = bpf_core_type_id_target (int);
+ v[i++] = bpf_core_type_id_target (named_struct_tdef);
+ v[i++] = bpf_core_type_id_target (func_tdef);
+ v[i++] = bpf_core_type_id_target (array_tdef);
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "\t.4byte\t0\t; bpfcr_type" 0 { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-times "\t.4byte\t0x6\t; bpfcr_kind" 13 } } BPF_TYPE_ID_LOCAL */
+/* { dg-final { scan-assembler-times "\t.4byte\t0x7\t; bpfcr_kind" 7 } } BPF_TYPE_ID_TARGET */
new file mode 100644
@@ -0,0 +1,109 @@
+struct my_struct {
+ int a;
+};
+
+union my_union {
+ int b;
+ int c;
+};
+
+typedef struct my_struct named_struct_tdef;
+typedef int (*func_tdef)(void *);
+
+typedef struct {
+ int d, e;
+} *tdef_struct_ptr;
+
+enum my_enum {
+ MY_ENUM_VAL1 = 1,
+ MY_ENUM_VAL2 = 2,
+};
+typedef enum { TE1, TE2, TE3 } enum_tdef;
+
+typedef int int_tdef;
+typedef void *void_ptr_tdef;
+typedef int *restrict restrict_ptr_tdef;
+typedef int (*func_tdef)(void *);
+typedef char array_tdef[10];
+
+struct my_complex_struct {
+ int a;
+ int b;
+ union {
+ int *a;
+ struct my_struct *s;
+ } c;
+};
+
+typedef struct {
+ int a;
+} anon_struct_tdef;
+
+typedef struct my_struct *struct_ptr_tdef;
+
+enum named_ue64 {
+ UE64_VAL1 = 0x1ffffffffULL,
+ UE64_VAL2 = 0x01fffffffULL,
+ UE64_VAL3 = 0x001ffffffULL,
+};
+
+enum named_se64 {
+ SE64_VAL1 = 0x1ffffffffLL,
+ SE64_VAL2 = 0x01fffffffLL,
+ SE64_VAL3 = -1,
+};
+
+enum named_ue {
+ UE_VAL1 = 0x1ffffff,
+ UE_VAL2 = 0x01fffff,
+ UE_VAL3 = 0x001ffff,
+};
+
+enum named_se {
+ SE_VAL1 = 0x1fffffff,
+ SE_VAL2 = 0x01ffffff,
+ SE_VAL3 = -1,
+};
+
+
+/* BPF specific code */
+
+enum bpf_type_id_kind {
+ BPF_TYPE_ID_LOCAL = 0,
+ BPF_TYPE_ID_TARGET = 1,
+};
+
+enum bpf_type_info_kind {
+ BPF_TYPE_EXISTS = 0,
+ BPF_TYPE_SIZE = 1,
+ BPF_TYPE_MATCHES = 2,
+};
+
+enum bpf_enum_value_kind {
+ BPF_ENUMVAL_EXISTS = 0,
+ BPF_ENUMVAL_VALUE = 1,
+};
+
+#define COMPOSE_VAR(t,s) t##s
+#define bpf_type1(type, NR) ({ \
+ extern typeof(type) *COMPOSE_VAR(bpf_type_tmp_, NR); \
+ COMPOSE_VAR(bpf_type_tmp_, NR); \
+})
+#define bpf_type(type) bpf_type1(type, __COUNTER__)
+
+#define bpf_core_type_id_local(type) \
+ __builtin_btf_type_id(*bpf_type(type), BPF_TYPE_ID_LOCAL)
+#define bpf_core_type_id_target(type) \
+ __builtin_btf_type_id(*bpf_type(type), BPF_TYPE_ID_TARGET)
+
+#define bpf_core_type_exists(type) \
+ __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_EXISTS)
+#define bpf_core_type_matches(type) \
+ __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_MATCHES)
+#define bpf_core_type_size(type) \
+ __builtin_preserve_type_info(*bpf_type(type), BPF_TYPE_SIZE)
+
+#define bpf_core_enum_value_exists(enum_type, enum_value) \
+ __builtin_preserve_enum_value(bpf_type(enum_type), enum_value, BPF_ENUMVAL_EXISTS)
+#define bpf_core_enum_value(enum_type, enum_value) \
+ __builtin_preserve_enum_value(bpf_type(enum_type), enum_value, BPF_ENUMVAL_VALUE)