+
+ if (TREE_CODE (t) == COMPONENT_REF)
+ {
+ tree base = TREE_OPERAND (t, 0);
+
+ bool base_is_attr = lookup_attribute ("preserve_access_index",
+ TYPE_ATTRIBUTES (TREE_TYPE (base)));
+ bool cur_is_attr = lookup_attribute ("preserve_access_index",
+ TYPE_ATTRIBUTES (TREE_TYPE (t)));
- tree lhs;
- if (!wi->is_lhs
- && gimple_code (wi->stmt) != GIMPLE_CALL
- && (lhs = gimple_get_lhs (wi->stmt)) != NULL_TREE)
- core_mark_as_access_index (lhs);
+ if (base_is_attr != cur_is_attr)
+ return true;
}
+ return false;
+}
+
+static tree
+gimple_core_early_split_expr (tree *tp,
+ int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data)
+{
+ struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+
+ if (core_should_split_expr (*tp))
+ {
+ gimple_seq before = NULL;
+ push_gimplify_context ();
+
+ tree base = TREE_OPERAND (*tp, 0);
+ walk_tree (&base, gimple_core_early_split_expr, data, NULL);
+ TREE_OPERAND (*tp, 0) = base;
+
+ if (POINTER_TYPE_P (TREE_TYPE (*tp)))
+ {
+ gimplify_expr (tp, &before, NULL, is_gimple_addressable, fb_lvalue);
+ }
+ else
+ {
+ tree tmp = fold_build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (*tp)), *tp);
+ gimplify_expr (&tmp, &before, NULL, is_gimple_val, fb_rvalue);
+ *tp = fold_build2 (MEM_REF, TREE_TYPE (tmp), tmp,
+ build_int_cst (ptr_type_node, 0));
+ }
+
+ gsi_insert_seq_before (&(wi->gsi), before, GSI_SAME_STMT);
+ pop_gimplify_context (NULL);
+ }
+
return NULL_TREE;
}
@@ -1851,11 +1846,13 @@ execute_lower_bpf_core (void)
gimple_seq body = gimple_body (current_function_decl);
struct walk_stmt_info wi;
- core_access_clean ();
-
memset (&wi, 0, sizeof (wi));
wi.info = NULL;
+ /* Early split to guarantee base of expression is a preserve_access_index
+ structure. */
+ walk_gimple_seq_mod (&body, NULL, gimple_core_early_split_expr, &wi);
+
/* Split preserve_access_index expressions when needed. */
walk_gimple_seq_mod (&body, NULL, make_gimple_core_safe_access_index, &wi);
return 0;
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-3.c
b/gcc/testsuite/gcc.target/bpf/core-attr-3.c
index 12354fc6f86..58c27fd43bb 100644
--- a/gcc/testsuite/gcc.target/bpf/core-attr-3.c
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-3.c
@@ -11,14 +11,14 @@
struct O {
int e;
int f;
-};
+} __attribute__((preserve_access_index));
struct S {
int a;
struct {
int b;
int c;
- } inner;
+ } __attribute__((preserve_access_index)) inner;
struct O other;
} __attribute__((preserve_access_index));
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-4.c b/gcc/testsuite/gcc.target/bpf/core-attr-4.c
index 6f025f42f3e..c001b5b76ef 100644
--- a/gcc/testsuite/gcc.target/bpf/core-attr-4.c
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-4.c
@@ -13,8 +13,8 @@ struct T {
int d;
int e[4];
int f;
- } v;
- } u;
+ } __attribute__((preserve_access_index)) v;
+ } __attribute__((preserve_access_index)) u;
} __attribute__((preserve_access_index));
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-5.c b/gcc/testsuite/gcc.target/bpf/core-attr-5.c
index 81e25fa85de..4d443d88b0a 100644
--- a/gcc/testsuite/gcc.target/bpf/core-attr-5.c
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-5.c
@@ -11,7 +11,7 @@ struct U {
int e[4];
int f;
int *g;
- } v;
+ } __attribute__((preserve_access_index)) v;
} __attribute__((preserve_access_index));
struct T {
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-6.c
b/gcc/testsuite/gcc.target/bpf/core-attr-6.c
index 25215b5ae37..d43825ea97c 100644
--- a/gcc/testsuite/gcc.target/bpf/core-attr-6.c
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-6.c
@@ -11,8 +11,8 @@ struct U {
int e[4];
int f;
int *g;
- } v;
-} u;
+ } __attribute__((preserve_access_index)) v;
+} __attribute__((preserve_access_index)) u;
struct T {
int a;
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-7.c
b/gcc/testsuite/gcc.target/bpf/core-attr-7.c
new file mode 100644
index 00000000000..5032fa8dba9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-7.c
@@ -0,0 +1,105 @@
+/* Test for BPF CO-RE __attribute__((preserve_access_index)) with accesses on
+ LHS and both LHS and RHS of assignment. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -dA -gbtf -mco-re -masm=normal" } */
+
+struct other
+{
+ char c;
+ int i;
+};
+
+struct inner_attr1
+{
+ int i1;
+ int i2;
+} __attribute__((preserve_access_index));
+
+struct inner_noattr
+{
+ int i1;
+ int i2;
+};
+
+union A_noattr
+{
+ struct inner_attr1 inner_attr;
+ struct inner_noattr inner_no_attr;
+ struct inner_noattr *inner_p;
+};
+union A_attr
+{
+ struct inner_attr1 inner_attr;
+ struct inner_noattr inner_no_attr;
+ struct inner_noattr *inner_p;
+} __attribute__((preserve_access_index));
+
+
+struct outer_noattr
+{
+ struct other *other;
+ struct inner_attr
+ {
+ int i1;
+ int i2;
+ } __attribute__((preserve_access_index)) inner;
+ struct inner_noattr inner_no_attr;
+ struct inner_attr1 *inner_p;
+ union A_attr a_attr;
+ union A_noattr a_noattr;
+};
+
+struct outer_attr
+{
+ struct other *other;
+ struct inner_attr
+ {
+ int i1;
+ int i2;
+ } __attribute__((preserve_access_index)) inner;
+
+ struct inner_noattr inner_no_attr;
+ struct inner_attr1 *inner_p;
+ union A_attr a_attr;
+ union A_noattr a_noattr;
+} __attribute__((preserve_access_index));
+
+
+void
+func (struct outer_noattr *o, struct outer_attr *o_attr)
+{
+ o->inner.i2 = 7;
+ o->inner_p->i2 = 8;
+ o->inner_no_attr.i2 = 9;
+
+ o_attr->inner_no_attr.i2 = 10;
+
+ o->a_noattr.inner_no_attr.i1 = 1;
+ o->a_attr.inner_no_attr.i1 = 2;
+ o->a_noattr.inner_attr.i1 = 3;
+ o_attr->a_attr.inner_attr.i1 = 4;
+ o_attr->a_noattr.inner_attr.i1 = 5;
+
+ /* This would still force everything as being attributed, although none of
+ the structs has the attribute. */
+ __builtin_preserve_access_index (({ o->a_noattr.inner_p->i1 = 20; }));
+}
+
+/* { dg-final { scan-assembler-times "ascii \"0:1.0\"\[\t
\]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:0.0\"\[\t
\]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2.0\"\[\t
\]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:5.0\"\[\t
\]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:4:0:0.0\"\[\t
\]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:5:2.0\"\[\t
\]+\[^\n\]*btf_aux_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:0\"\\)" 3 } } */
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:1\"\\)" 3 } } */
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:2\"\\)" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:5\"\\)" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:4:0:0\"\\)" 1 } }
*/
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:5:2\"\\)" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_type \\(struct inner_attr\\)" 1 }
} */
+/* { dg-final { scan-assembler-times "bpfcr_type \\(struct inner_attr1\\)" 3 }
} */
+/* { dg-final { scan-assembler-times "bpfcr_type \\(struct outer_attr\\)" 3 }
} */
+/* { dg-final { scan-assembler-times "bpfcr_type \\(union A_attr\\)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/core-attr-calls.c
b/gcc/testsuite/gcc.target/bpf/core-attr-calls.c
index 87290c5c211..27b08af1bb7 100644
--- a/gcc/testsuite/gcc.target/bpf/core-attr-calls.c
+++ b/gcc/testsuite/gcc.target/bpf/core-attr-calls.c
@@ -37,13 +37,13 @@ func (struct T *t, int i)
/* 0:3 */
get_other_u(t->ptr_u)->c = 43;
- /* 0:2:1 */
+ /* 0:2 */
get_other_v(&t->u.v)->d = 44;
}
/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:3\"\\)" 2 } } */
/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:0\"\\)" 1 } } */
-/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:2:1\"\\)" 1 } } */
+/* { dg-final { scan-assembler-times "bpfcr_astr_off \\(\"0:2\"\\)" 1 } } */
/* { dg-final { scan-assembler-times "bpfcr_type \\(struct T\\)" 3 } } */
/* { dg-final { scan-assembler-times "bpfcr_type \\(struct U\\)" 1 } } */