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
{
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)));
+
+ HOST_WIDE_INT offset_i = tree_to_shwi (offset);
+ result += offset_i;
+ }
+
type = unsigned_type_node;
if (var_off != NULL_TREE)
{
}
if (bitfieldp)
- result = start_bitpos / 8;
+ result += start_bitpos / 8;
else
- result = bitpos / 8;
+ result += bitpos / 8;
}
break;
{
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)))
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,
access_node, false);
return n;
+ case ADDR_EXPR:
case CALL_EXPR:
case SSA_NAME:
case VAR_DECL:
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];
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)
{
if (base == NULL_TREE || base == expr)
return expr;
+ base = expr;
+
tree ret = NULL_TREE;
int n;
bool valid = 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);
--- /dev/null
+/* 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 } } */