From a278b1c38f8bc1f14f6d07c303b81a8856491efa Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 9 Mar 2017 10:26:45 +0100 Subject: [PATCH] Support BIT_FIELD_REF in MPX (PR ipa/79764). 2017-03-09 Martin Liska PR ipa/79764 (chkp_narrow_size_and_offset): New function. (chkp_parse_array_and_component_ref): Support BIT_FIELD_REF. (void chkp_parse_bit_field_ref): New function. (chkp_make_addressed_object_bounds): Add case for BIT_FIELD_REF. (chkp_process_stmt): Use chkp_parse_bit_field_ref. 2017-03-09 Martin Liska PR ipa/79764 * g++.dg/pr79764.C: New test. From-SVN: r245994 --- gcc/ChangeLog | 9 ++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/pr79764.C | 12 +++++ gcc/tree-chkp.c | 88 +++++++++++++++++++++++++++------- 4 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr79764.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b3ab72b3d82..752a5324b0d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-03-09 Martin Liska + + PR ipa/79764 + (chkp_narrow_size_and_offset): New function. + (chkp_parse_array_and_component_ref): Support BIT_FIELD_REF. + (void chkp_parse_bit_field_ref): New function. + (chkp_make_addressed_object_bounds): Add case for BIT_FIELD_REF. + (chkp_process_stmt): Use chkp_parse_bit_field_ref. + 2017-03-09 Martin Liska PR ipa/79761 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 371fdbb8428..4c8ee64b255 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-03-09 Martin Liska + + PR ipa/79764 + * g++.dg/pr79764.C: New test. + 2017-03-09 Martin Liska PR ipa/79761 diff --git a/gcc/testsuite/g++.dg/pr79764.C b/gcc/testsuite/g++.dg/pr79764.C new file mode 100644 index 00000000000..293aa337693 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr79764.C @@ -0,0 +1,12 @@ +/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && { ! x32 } } } } */ +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ + +typedef float __m256 __attribute__ (( __vector_size__(32), __may_alias__ )); +struct A { + __m256 ymm; + const float &f() const; +}; + +const float &A::f() const { + return ymm[1]; +} diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c index 66612baaaff..acd57eac5ef 100644 --- a/gcc/tree-chkp.c +++ b/gcc/tree-chkp.c @@ -325,6 +325,8 @@ static void chkp_parse_array_and_component_ref (tree node, tree *ptr, tree *bounds, gimple_stmt_iterator *iter, bool innermost_bounds); +static void chkp_parse_bit_field_ref (tree node, location_t loc, + tree *offset, tree *size); #define chkp_bndldx_fndecl \ (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDLDX)) @@ -3295,7 +3297,7 @@ chkp_narrow_bounds_for_field (tree ref, tree field) if (!chkp_may_narrow_to_field (ref, field)) return false; - /* Accesse to compiler generated fields should not cause + /* Access to compiler generated fields should not cause bounds narrowing. */ if (DECL_ARTIFICIAL (field)) return false; @@ -3309,9 +3311,36 @@ chkp_narrow_bounds_for_field (tree ref, tree field) || bit_offs)); } +/* Perform narrowing for BOUNDS of an INNER reference. Shift boundary + by OFFSET bytes and limit to SIZE bytes. Newly created statements are + added to ITER. */ + +static tree +chkp_narrow_size_and_offset (tree bounds, tree inner, tree offset, + tree size, gimple_stmt_iterator *iter) +{ + tree addr = chkp_build_addr_expr (unshare_expr (inner)); + tree t = TREE_TYPE (addr); + + gimple *stmt = gimple_build_assign (NULL_TREE, addr); + addr = make_temp_ssa_name (t, stmt, CHKP_BOUND_TMP_NAME); + gimple_assign_set_lhs (stmt, addr); + gsi_insert_seq_before (iter, stmt, GSI_SAME_STMT); + + stmt = gimple_build_assign (NULL_TREE, POINTER_PLUS_EXPR, addr, offset); + tree shifted = make_temp_ssa_name (t, stmt, CHKP_BOUND_TMP_NAME); + gimple_assign_set_lhs (stmt, shifted); + gsi_insert_seq_before (iter, stmt, GSI_SAME_STMT); + + tree bounds2 = chkp_make_bounds (shifted, size, iter, false); + + return chkp_intersect_bounds (bounds, bounds2, iter); +} + /* Perform narrowing for BOUNDS using bounds computed for field access COMPONENT. ITER meaning is the same as for chkp_intersect_bounds. */ + static tree chkp_narrow_bounds_to_field (tree bounds, tree component, gimple_stmt_iterator *iter) @@ -3364,7 +3393,8 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr, len = 1; while (TREE_CODE (var) == COMPONENT_REF || TREE_CODE (var) == ARRAY_REF - || TREE_CODE (var) == VIEW_CONVERT_EXPR) + || TREE_CODE (var) == VIEW_CONVERT_EXPR + || TREE_CODE (var) == BIT_FIELD_REF) { var = TREE_OPERAND (var, 0); len++; @@ -3383,9 +3413,10 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr, if (bounds) *bounds = NULL; *safe = true; - *bitfield = (TREE_CODE (node) == COMPONENT_REF - && DECL_BIT_FIELD_TYPE (TREE_OPERAND (node, 1))); - /* To get bitfield address we will need outer elemnt. */ + *bitfield = ((TREE_CODE (node) == COMPONENT_REF + && DECL_BIT_FIELD_TYPE (TREE_OPERAND (node, 1))) + || TREE_CODE (node) == BIT_FIELD_REF); + /* To get bitfield address we will need outer element. */ if (*bitfield) *elt = nodes[len - 2]; else @@ -3455,6 +3486,17 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr, comp_to_narrow = NULL; } } + else if (TREE_CODE (var) == BIT_FIELD_REF) + { + if (flag_chkp_narrow_bounds && bounds) + { + tree offset, size; + chkp_parse_bit_field_ref (var, UNKNOWN_LOCATION, &offset, &size); + *bounds + = chkp_narrow_size_and_offset (*bounds, TREE_OPERAND (var, 0), + offset, size, iter); + } + } else if (TREE_CODE (var) == VIEW_CONVERT_EXPR) /* Nothing to do for it. */ ; @@ -3469,6 +3511,27 @@ chkp_parse_array_and_component_ref (tree node, tree *ptr, *bounds = chkp_find_bounds (*ptr, iter); } +/* Parse BIT_FIELD_REF to a NODE for a given location LOC. Return OFFSET + and SIZE in bytes. */ + +static +void chkp_parse_bit_field_ref (tree node, location_t loc, tree *offset, + tree *size) +{ + tree bpu = fold_convert (size_type_node, bitsize_int (BITS_PER_UNIT)); + tree offs = fold_convert (size_type_node, TREE_OPERAND (node, 2)); + tree rem = size_binop_loc (loc, TRUNC_MOD_EXPR, offs, bpu); + offs = size_binop_loc (loc, TRUNC_DIV_EXPR, offs, bpu); + + tree s = fold_convert (size_type_node, TREE_OPERAND (node, 1)); + s = size_binop_loc (loc, PLUS_EXPR, s, rem); + s = size_binop_loc (loc, CEIL_DIV_EXPR, s, bpu); + s = fold_convert (size_type_node, s); + + *offset = offs; + *size = s; +} + /* Compute and return bounds for address of OBJ. */ static tree chkp_make_addressed_object_bounds (tree obj, gimple_stmt_iterator *iter) @@ -3492,6 +3555,7 @@ chkp_make_addressed_object_bounds (tree obj, gimple_stmt_iterator *iter) case ARRAY_REF: case COMPONENT_REF: + case BIT_FIELD_REF: { tree elt; tree ptr; @@ -3993,23 +4057,15 @@ chkp_process_stmt (gimple_stmt_iterator *iter, tree node, case BIT_FIELD_REF: { - tree offs, rem, bpu; + tree offset, size; gcc_assert (!access_offs); gcc_assert (!access_size); - bpu = fold_convert (size_type_node, bitsize_int (BITS_PER_UNIT)); - offs = fold_convert (size_type_node, TREE_OPERAND (node, 2)); - rem = size_binop_loc (loc, TRUNC_MOD_EXPR, offs, bpu); - offs = size_binop_loc (loc, TRUNC_DIV_EXPR, offs, bpu); - - size = fold_convert (size_type_node, TREE_OPERAND (node, 1)); - size = size_binop_loc (loc, PLUS_EXPR, size, rem); - size = size_binop_loc (loc, CEIL_DIV_EXPR, size, bpu); - size = fold_convert (size_type_node, size); + chkp_parse_bit_field_ref (node, loc, &offset, &size); chkp_process_stmt (iter, TREE_OPERAND (node, 0), loc, - dirflag, offs, size, safe); + dirflag, offset, size, safe); return; } break; -- 2.30.2