2017-04-20 12:27 GMT+03:00 Alexander Ivchenko <aivch...@gmail.com>: > Thanks for correcting the usage of get_base_address. I fixed that. > Plus addressed the comment about the avoiding the usage of > chkp_find_bounds. > > > gcc/testsuite/ChangeLog: > > 2017-04-20 Alexander Ivchenko <alexander.ivche...@intel.com> > > * gcc.target/i386/mpx/hard-reg-2-lbv.c: New test. > * gcc.target/i386/mpx/hard-reg-2-nov.c: New test. > * gcc.target/i386/mpx/hard-reg-2-ubv.c: New test. > * gcc.target/i386/mpx/hard-reg-3-1-lbv.c: New test. > * gcc.target/i386/mpx/hard-reg-3-1-nov.c: New test. > * gcc.target/i386/mpx/hard-reg-3-1-ubv.c: New test. > * gcc.target/i386/mpx/hard-reg-3-2-lbv.c: New test. > * gcc.target/i386/mpx/hard-reg-3-2-nov.c: New test. > * gcc.target/i386/mpx/hard-reg-3-2-ubv.c: New test. > * gcc.target/i386/mpx/hard-reg-3-lbv.c: New test. > * gcc.target/i386/mpx/hard-reg-3-nov.c: New test. > * gcc.target/i386/mpx/hard-reg-3-ubv.c: New test. > * gcc.target/i386/mpx/hard-reg-4-lbv.c: New test. > * gcc.target/i386/mpx/hard-reg-4-nov.c: New test. > * gcc.target/i386/mpx/hard-reg-4-ubv.c: New test. > * gcc.target/i386/mpx/hard-reg-5-1-lbv.c: New test. > * gcc.target/i386/mpx/hard-reg-5-1-nov.c: New test. > * gcc.target/i386/mpx/hard-reg-5-1-ubv.c: New test. > * gcc.target/i386/mpx/hard-reg-5-2-lbv.c: New test. > * gcc.target/i386/mpx/hard-reg-5-2-nov.c: New test. > * gcc.target/i386/mpx/hard-reg-5-2-ubv.c: New test. > * gcc.target/i386/mpx/hard-reg-6-lbv.c: New test. > * gcc.target/i386/mpx/hard-reg-6-nov.c: New test. > * gcc.target/i386/mpx/hard-reg-6-ubv.c: New test. > > gcc/ChangeLog: > > 2017-04-20 Alexander Ivchenko <alexander.ivche...@intel.com> > > * tree-chkp.c (chkp_get_hard_register_var_fake_base_address): > New function to provide a base address for > chkp_get_hard_register_fake_addr_expr. > (chkp_get_hard_register_fake_addr_expr): New function to build > fake address expression for an expr that resides on a hard > register. > (chkp_build_addr_expr): Add checks for hard reg cases. > (chkp_parse_array_and_component_ref): Create/find bounds if the > var resides on a hard reg. > > > I already had a testcases for struct with a pointer - "hard-reg-4-*". > Here is the instrumentation of the foo function: > > __attribute__((chkp instrumented)) > foo.chkp (int i) > { > __bounds_type __bound_tmp.1; > register struct S2 b __asm__ (*xmm0); > int k; > int * _1; > long unsigned int _2; > long unsigned int _3; > int * _4; > int * _5; > int _11; > int * _18; > > <bb 4> [0.00%]: > __bound_tmp.1_17 = __chkp_zero_bounds; > __bound_tmp.1_14 = __builtin_ia32_bndmk (&k, 4); > __bound_tmp.1_13 = __builtin_ia32_bndmk (-2147483648B, 16); > > <bb 3> [0.00%]: > > <bb 2> [0.00%]: > k = 5; > b.f3 = &k; > __builtin_ia32_bndstx (&k, __bound_tmp.1_14, -2147483648B); > _1 = b.f3; > __bound_tmp.1_15 = __builtin_ia32_bndldx (-2147483648B, _1); > _2 = (long unsigned int) i_9(D); > _3 = _2 * 4; > _4 = _1 + _3; > b.f3 = _4; > __builtin_ia32_bndstx (_4, __bound_tmp.1_15, -2147483648B); > _5 = b.f3; > __bound_tmp.1_16 = __builtin_ia32_bndldx (-2147483648B, _5); > __builtin_ia32_bndcl (_5, __bound_tmp.1_16); > _18 = _5 + 3; > __builtin_ia32_bndcu (_18, __bound_tmp.1_16); > _11 = *_5; > k ={v} {CLOBBER}; > return _11; > > } > > Which is the most suspicious one, because we have ldx and stx. I'm not > sure whether this is OK.
It is not OK because single entry in BT may be used by multiple hardreg variables. There is a code in chkp_find_bounds_1 to use zero bounds in case we load bounds from register var. I believe here we should do the same. In chkp_find_bounds_1 at ARRAY_REF/COMPONENT_REF case check if addr is register var and use zero bounds. Thanks, Ilya > > Here is the chkp dump for foo function of newly added hard-reg-6* case: > > __attribute__((chkp instrumented)) > foo.chkp (int i, int * kp1, __bounds_type __chkp_bounds_of_kp1) > { > __bounds_type __bound_tmp.1; > int D.2873; > register struct S2 b __asm__ (*xmm0); > int k2; > int * _1; > long unsigned int _2; > long unsigned int _3; > int * _4; > int * _5; > int _13; > int * _31; > > <bb 5> [0.00%]: > __bound_tmp.1_22 = __builtin_ia32_bndmk (&k2, 4); > __bound_tmp.1_17 = __chkp_zero_bounds; > __bound_tmp.1_15 = __builtin_ia32_bndmk (-2147483648B, 16); > > <bb 4> [0.00%]: > > <bb 2> [0.00%]: > k2 = 5; > __bound_tmp.1_16 = __builtin_ia32_bndmk (-2147483648B, 16); > __bound_tmp.1_18 = __builtin_ia32_bndint (__bound_tmp.1_16, > __bound_tmp.1_15); > __builtin_ia32_bndcl (-2147483648B, __bound_tmp.1_18); > __builtin_ia32_bndcu (-2147483641B, __bound_tmp.1_18); > b.f[0] = kp1_8(D); > __builtin_ia32_bndstx (kp1_8(D), __chkp_bounds_of_kp1_19(D), -2147483648B); > __bound_tmp.1_20 = __builtin_ia32_bndmk (-2147483648B, 16); > __bound_tmp.1_21 = __builtin_ia32_bndint (__bound_tmp.1_20, > __bound_tmp.1_15); > __builtin_ia32_bndcl (-2147483640B, __bound_tmp.1_21); > __builtin_ia32_bndcu (-2147483633B, __bound_tmp.1_21); > b.f[1] = &k2; > __builtin_ia32_bndstx (&k2, __bound_tmp.1_22, -2147483640B); > __bound_tmp.1_23 = __builtin_ia32_bndmk (-2147483648B, 16); > __bound_tmp.1_24 = __builtin_ia32_bndint (__bound_tmp.1_23, > __bound_tmp.1_15); > __builtin_ia32_bndcl (-2147483648B, __bound_tmp.1_24); > __builtin_ia32_bndcu (-2147483641B, __bound_tmp.1_24); > _1 = b.f[0]; > __bound_tmp.1_27 = __builtin_ia32_bndldx (-2147483648B, _1); > _2 = (long unsigned int) i_11(D); > _3 = _2 * 4; > _4 = _1 + _3; > __bound_tmp.1_25 = __builtin_ia32_bndmk (-2147483648B, 16); > __bound_tmp.1_26 = __builtin_ia32_bndint (__bound_tmp.1_25, > __bound_tmp.1_15); > __builtin_ia32_bndcl (-2147483648B, __bound_tmp.1_26); > __builtin_ia32_bndcu (-2147483641B, __bound_tmp.1_26); > b.f[0] = _4; > __builtin_ia32_bndstx (_4, __bound_tmp.1_27, -2147483648B); > __bound_tmp.1_28 = __builtin_ia32_bndmk (-2147483648B, 16); > __bound_tmp.1_29 = __builtin_ia32_bndint (__bound_tmp.1_28, > __bound_tmp.1_15); > __builtin_ia32_bndcl (-2147483648B, __bound_tmp.1_29); > __builtin_ia32_bndcu (-2147483641B, __bound_tmp.1_29); > _5 = b.f[0]; > __bound_tmp.1_30 = __builtin_ia32_bndldx (-2147483648B, _5); > __builtin_ia32_bndcl (_5, __bound_tmp.1_30); > _31 = _5 + 3; > __builtin_ia32_bndcu (_31, __bound_tmp.1_30); > _13 = *_5; > k2 ={v} {CLOBBER}; > > <L0> [0.00%]: > return _13; > } > > ..which looks fine to me. And here is the dump-chkp for the basic case > of hard-reg-2: > > __attribute__((chkp instrumented)) > foo.chkp (int i) > { > __bounds_type __bound_tmp.1; > int D.2863; > register v16 u __asm__ (*xmm0); > int _3; > long unsigned int _6; > sizetype _7; > void * _8; > sizetype _9; > sizetype _10; > sizetype _11; > sizetype _12; > void * _13; > > <bb 5> [0.00%]: > __bound_tmp.1_5 = __chkp_zero_bounds; > __bound_tmp.1_4 = __builtin_ia32_bndmk (-2147483648B, 16); > > <bb 4> [0.00%]: > > <bb 2> [0.00%]: > _6 = (long unsigned int) i_2(D); > _7 = _6 * 4; > _8 = -2147483648B + _7; > __builtin_ia32_bndcl (_8, __bound_tmp.1_4); > _9 = (sizetype) i_2(D); > _10 = _9 + 1; > _11 = _10 * 4; > _12 = _11 + 18446744073709551615; > _13 = -2147483648B + _12; > __builtin_ia32_bndcu (_13, __bound_tmp.1_4); > _3 = VIEW_CONVERT_EXPR<int[4]>(u)[i_2(D)]; > > <L0> [0.00%]: > return _3; > > } > > So overall we have these fails (they all have the same backtrace as > PR80270) and other combinations pass: > > FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O3 -g (internal compiler > error) > FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O3 -g (test for excess > errors) > FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto > -fno-use-linker-plugin -flto-partition=none (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto > -fno-use-linker-plugin -flto-partition=none (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto > -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto > -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O3 -g (internal compiler > error) > FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O3 -g (test for excess > errors) > FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto > -fno-use-linker-plugin -flto-partition=none (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto > -fno-use-linker-plugin -flto-partition=none (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto > -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto > -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-4-lbv.c -O0 (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-4-lbv.c -O0 (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-4-nov.c -O0 (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-4-nov.c -O0 (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-4-ubv.c -O0 (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-4-ubv.c -O0 (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O3 -g (internal compiler > error) > FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O3 -g (test for excess > errors) > FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto > -fno-use-linker-plugin -flto-partition=none (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto > -fno-use-linker-plugin -flto-partition=none (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto > -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto > -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) > FAIL: gcc.target/i386/mpx/hard-reg-6-lbv.c -O0 (internal compiler error) > FAIL: gcc.target/i386/mpx/hard-reg-6-lbv.c -O0 (test for excess errors) > > > > Here is the patch itself: > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c > new file mode 100644 > index 0000000..319e1ec > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c > @@ -0,0 +1,21 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v16 __attribute__((vector_size(16))); > + > +int foo(int i) { > + register v16 u asm("xmm0"); > + return u[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo (-1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c > new file mode 100644 > index 0000000..3c6d39a > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c > @@ -0,0 +1,18 @@ > +/* { dg-do run } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > +#include "mpx-check.h" > + > +typedef int v16 __attribute__((vector_size(16))); > + > +int foo (int i) { > + register v16 u asm ("xmm0"); > + return u[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo (3)); > + printf ("%d\n", foo (0)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c > new file mode 100644 > index 0000000..7fe76c4 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c > @@ -0,0 +1,21 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v16 __attribute__((vector_size(16))); > + > +int foo (int i) { > + register v16 u asm ("xmm0"); > + return u[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo (5)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c > new file mode 100644 > index 0000000..7e4451f > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c > @@ -0,0 +1,33 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1; > + v8 s2f2; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1.s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (-1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c > new file mode 100644 > index 0000000..73bd7fb > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c > @@ -0,0 +1,30 @@ > +/* { dg-do run } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1; > + v8 s2f2; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1.s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (0)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c > new file mode 100644 > index 0000000..166b6b9 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c > @@ -0,0 +1,33 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1; > + v8 s2f2; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1.s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (3)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c > new file mode 100644 > index 0000000..7820c2f > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c > @@ -0,0 +1,33 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1; > + v8 s2f2; > +}; > + > +int foo_s2f2 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f2[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f2 (-1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c > new file mode 100644 > index 0000000..0816e58 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c > @@ -0,0 +1,30 @@ > +/* { dg-do run } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1; > + v8 s2f2; > +}; > + > +int foo_s2f2 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f2[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f2 (0)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c > new file mode 100644 > index 0000000..94261a7 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c > @@ -0,0 +1,33 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1; > + v8 s2f2; > +}; > + > +int foo_s2f2 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f2[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f2 (3)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c > new file mode 100644 > index 0000000..f273d58 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c > @@ -0,0 +1,27 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v16 __attribute__ ((vector_size (16))); > + > +struct S1 > +{ > + v16 s1f1; > +}; > + > +int foo_s1f1 (int i) > +{ > + register struct S1 b asm ("xmm0"); > + return b.s1f1[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s1f1 (-1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c > new file mode 100644 > index 0000000..aa8f7b9 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c > @@ -0,0 +1,24 @@ > +/* { dg-do run } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#include "mpx-check.h" > + > +typedef int v16 __attribute__ ((vector_size (16))); > + > +struct S1 > +{ > + v16 s1f1; > +}; > + > +int foo_s1f1 (int i) > +{ > + register struct S1 b asm ("xmm0"); > + return b.s1f1[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s1f1 (0)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c > new file mode 100644 > index 0000000..3d0c9b2 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c > @@ -0,0 +1,27 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v16 __attribute__ ((vector_size (16))); > + > +struct S1 > +{ > + v16 s1f1; > +}; > + > +int foo_s1f1 (int i) > +{ > + register struct S1 b asm ("xmm0"); > + return b.s1f1[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s1f1 (7)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c > new file mode 100644 > index 0000000..e81b942 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c > @@ -0,0 +1,31 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S2 > +{ > + v8 s2f2; > + int* f3; > +}; > + > +int foo (int i) > +{ > + register struct S2 b asm ("xmm0"); > + int k = 5; > + b.f3 = &k; > + b.f3 = b.f3 + i; > + return *b.f3; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo (-1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c > new file mode 100644 > index 0000000..4b1f1ac > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c > @@ -0,0 +1,28 @@ > +/* { dg-do run } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S2 > +{ > + v8 s2f2; > + int* f3; > +}; > + > +int foo (int i) > +{ > + register struct S2 b asm ("xmm0"); > + int k = 5; > + b.f3 = &k; > + b.f3 = b.f3 + i; > + return *b.f3; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo (0)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c > new file mode 100644 > index 0000000..e95e68f > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c > @@ -0,0 +1,31 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S2 > +{ > + v8 s2f2; > + int* f3; > +}; > + > +int foo (int i) > +{ > + register struct S2 b asm ("xmm0"); > + int k = 5; > + b.f3 = &k; > + b.f3 = b.f3 + i; > + return *b.f3; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo (1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c > new file mode 100644 > index 0000000..201b62d > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c > @@ -0,0 +1,32 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1[2]; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1[0].s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (-1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c > new file mode 100644 > index 0000000..f94a879 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c > @@ -0,0 +1,30 @@ > +/* { dg-do run } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1[2]; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1[0].s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c > new file mode 100644 > index 0000000..6ab981d > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c > @@ -0,0 +1,32 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1[2]; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1[0].s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (4)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c > new file mode 100644 > index 0000000..cc58e8a > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c > @@ -0,0 +1,32 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1[2]; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1[1].s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (-1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c > new file mode 100644 > index 0000000..5898c3b > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c > @@ -0,0 +1,30 @@ > +/* { dg-do run } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1[2]; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1[1].s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c > new file mode 100644 > index 0000000..2910795 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c > @@ -0,0 +1,32 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S1 > +{ > + v8 s1f; > +}; > + > +struct S2 > +{ > + struct S1 s2f1[2]; > +}; > + > +int foo_s2f1 (int i) > +{ > + register struct S2 b asm ("xmm0"); > + return b.s2f1[1].s1f[i]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + printf ("%d\n", foo_s2f1 (4)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-lbv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-lbv.c > new file mode 100644 > index 0000000..b160915 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-lbv.c > @@ -0,0 +1,34 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S2 > +{ > + int* f[2]; > +}; > + > +int foo (int i, int *kp1) > +{ > + register struct S2 b asm ("xmm0"); > + int k2 = 5; > + > + b.f[0] = kp1; > + b.f[1] = &k2; > + > + b.f[1] = b.f[1] + i; > + return *b.f[1]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + int k1 = 10; > + printf ("%d\n", foo (-1, &k1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-nov.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-nov.c > new file mode 100644 > index 0000000..584b3e5 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-nov.c > @@ -0,0 +1,31 @@ > +/* { dg-do run } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S2 > +{ > + int* f[2]; > +}; > + > +int foo (int i, int *kp1) > +{ > + register struct S2 b asm ("xmm0"); > + int k2 = 5; > + > + b.f[0] = kp1; > + b.f[1] = &k2; > + > + b.f[0] = b.f[0] + i; > + return *b.f[0]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + int k1 = 10; > + printf ("%d\n", foo (0, &k1)); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-ubv.c > b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-ubv.c > new file mode 100644 > index 0000000..92fa793 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-6-ubv.c > @@ -0,0 +1,34 @@ > +/* { dg-do run } */ > +/* { dg-shouldfail "bounds violation" } */ > +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ > + > + > +#define SHOULDFAIL > + > +#include "mpx-check.h" > + > +typedef int v8 __attribute__ ((vector_size (8))); > + > +struct S2 > +{ > + int* f[2]; > +}; > + > +int foo (int i, int *kp1) > +{ > + register struct S2 b asm ("xmm0"); > + int k2 = 5; > + > + b.f[0] = kp1; > + b.f[1] = &k2; > + > + b.f[0] = b.f[0] + i; > + return *b.f[0]; > +} > + > +int mpx_test (int argc, const char **argv) > +{ > + int k1 = 10; > + printf ("%d\n", foo (1, &k1)); > + return 0; > +} > diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c > index b1ff218..3ef73a9 100644 > --- a/gcc/tree-chkp.c > +++ b/gcc/tree-chkp.c > @@ -327,6 +327,8 @@ static void chkp_parse_array_and_component_ref > (tree node, tree *ptr, > bool innermost_bounds); > static void chkp_parse_bit_field_ref (tree node, location_t loc, > tree *offset, tree *size); > +static tree > +chkp_make_addressed_object_bounds (tree obj, gimple_stmt_iterator *iter); > > #define chkp_bndldx_fndecl \ > (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDLDX)) > @@ -679,6 +681,45 @@ chkp_erase_completed_bounds (void) > chkp_completed_bounds_set = new hash_set<tree>; > } > > +/* This function is used to provide a base address for > + chkp_get_hard_register_fake_addr_expr. */ > +static tree > +chkp_get_hard_register_var_fake_base_address () > +{ > + tree base = fold_convert (ptr_type_node, integer_zero_node); > + unsigned HOST_WIDE_INT offset = 1 << (TYPE_PRECISION (ptr_type_node) - 1); > + return fold_build_pointer_plus_hwi (base, offset); > +} > + > +/* If we check bounds for a hard register variable, we cannot > + use its address - it is illegal, so instead of that we use > + this fake value. */ > +static tree > +chkp_get_hard_register_fake_addr_expr (tree obj) > +{ > + tree addr = chkp_get_hard_register_var_fake_base_address (); > + tree outer = obj; > + while (TREE_CODE (outer) == COMPONENT_REF || TREE_CODE (outer) == > ARRAY_REF) > + { > + if (TREE_CODE (outer) == COMPONENT_REF) > + { > + addr = fold_build_pointer_plus (addr, > + component_ref_field_offset (outer)); > + outer = TREE_OPERAND (outer, 0); > + } > + else if (TREE_CODE (outer) == ARRAY_REF) > + { > + tree indx = fold_convert(size_type_node, TREE_OPERAND(outer, 1)); > + tree offset = size_binop (MULT_EXPR, > + array_ref_element_size (outer), indx); > + addr = fold_build_pointer_plus (addr, offset); > + outer = TREE_OPERAND (outer, 0); > + } > + } > + > + return addr; > +} > + > /* Mark BOUNDS associated with PTR as incomplete. */ > static void > chkp_register_incomplete_bounds (tree bounds, tree ptr) > @@ -1044,6 +1085,12 @@ chkp_add_modification_to_stmt_list (tree lhs, > static tree > chkp_build_addr_expr (tree obj) > { > + /* We first check whether it is a "hard reg case". */ > + tree base = get_base_address (obj); > + if (VAR_P (base) && DECL_HARD_REGISTER (base)) > + return chkp_get_hard_register_fake_addr_expr (obj); > + > + /* If not - return regular ADDR_EXPR. */ > return TREE_CODE (obj) == TARGET_MEM_REF > ? tree_mem_ref_addr (ptr_type_node, obj) > : build_fold_addr_expr (obj); > @@ -3442,6 +3489,13 @@ chkp_parse_array_and_component_ref (tree node, tree > *ptr, > || TREE_CODE (var) == SSA_NAME); > > *ptr = chkp_build_addr_expr (var); > + > + /* For hard register cases chkp_build_addr_expr returns INTEGER_CST > + and later on chkp_find_bounds will fail to find proper bounds. > + In order to avoid that, we find/create bounds right aways using > + the var itself. */ > + if (DECL_HARD_REGISTER (var)) > + *bounds = chkp_make_addressed_object_bounds (var, iter); > } > > /* In this loop we are trying to find a field access > > 2017-04-19 21:32 GMT+02:00 Ilya Enkovich <enkovich....@gmail.com>: >> 2017-04-19 19:48 GMT+03:00 Alexander Ivchenko <aivch...@gmail.com>: >>> Hi, >>> >>> Thanks for the comments, that was a good idea to place all the logic inside >>> of chkp_build_addr_expr function. I followed it and here is what I got: >>> >>> gcc/testsuite/ChangeLog: >>> >>> 2017-04-19 Alexander Ivchenko <aivch...@gmail.com> >>> >>> * gcc.target/i386/mpx/hard-reg-2-lbv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-2-nov.c: New test. >>> * gcc.target/i386/mpx/hard-reg-2-ubv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-1-lbv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-1-nov.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-1-ubv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-2-lbv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-2-nov.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-2-ubv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-lbv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-nov.c: New test. >>> * gcc.target/i386/mpx/hard-reg-3-ubv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-4-lbv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-4-nov.c: New test. >>> * gcc.target/i386/mpx/hard-reg-4-ubv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-5-1-lbv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-5-1-nov.c: New test. >>> * gcc.target/i386/mpx/hard-reg-5-1-ubv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-5-2-lbv.c: New test. >>> * gcc.target/i386/mpx/hard-reg-5-2-nov.c: New test. >>> * gcc.target/i386/mpx/hard-reg-5-2-ubv.c: New test. >>> >>> gcc/ChangeLog: >>> >>> 2017-04-19 Alexander Ivchenko <aivch...@gmail.com> >>> >>> * tree-chkp.c (chkp_get_hard_register_var_fake_base_address): >>> New function to provide a base address for. >>> chkp_get_hard_register_fake_addr_expr >>> (chkp_get_hard_register_fake_addr_expr): New function to build >>> fake address expression for an expr that resides on a hard >>> register. >>> (chkp_build_addr_expr): Add checks for hard reg cases. >>> (chkp_parse_array_and_component_ref): Create/find bounds if the >>> var resides on a hard reg. >>> (chkp_find_bounds_1): Check for hard register cases. >>> >>> >>> >>> >>> >>> And the patch itself: >>> >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c >>> new file mode 100644 >>> index 0000000..319e1ec >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c >>> @@ -0,0 +1,21 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v16 __attribute__((vector_size(16))); >>> + >>> +int foo(int i) { >>> + register v16 u asm("xmm0"); >>> + return u[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo (-1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c >>> new file mode 100644 >>> index 0000000..3c6d39a >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c >>> @@ -0,0 +1,18 @@ >>> +/* { dg-do run } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v16 __attribute__((vector_size(16))); >>> + >>> +int foo (int i) { >>> + register v16 u asm ("xmm0"); >>> + return u[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo (3)); >>> + printf ("%d\n", foo (0)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c >>> new file mode 100644 >>> index 0000000..7fe76c4 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c >>> @@ -0,0 +1,21 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v16 __attribute__((vector_size(16))); >>> + >>> +int foo (int i) { >>> + register v16 u asm ("xmm0"); >>> + return u[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo (5)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c >>> new file mode 100644 >>> index 0000000..7e4451f >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c >>> @@ -0,0 +1,33 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1; >>> + v8 s2f2; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1.s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (-1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c >>> new file mode 100644 >>> index 0000000..73bd7fb >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c >>> @@ -0,0 +1,30 @@ >>> +/* { dg-do run } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1; >>> + v8 s2f2; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1.s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (0)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c >>> new file mode 100644 >>> index 0000000..166b6b9 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c >>> @@ -0,0 +1,33 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1; >>> + v8 s2f2; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1.s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (3)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c >>> new file mode 100644 >>> index 0000000..7820c2f >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c >>> @@ -0,0 +1,33 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1; >>> + v8 s2f2; >>> +}; >>> + >>> +int foo_s2f2 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f2[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f2 (-1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c >>> new file mode 100644 >>> index 0000000..0816e58 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c >>> @@ -0,0 +1,30 @@ >>> +/* { dg-do run } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1; >>> + v8 s2f2; >>> +}; >>> + >>> +int foo_s2f2 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f2[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f2 (0)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c >>> new file mode 100644 >>> index 0000000..94261a7 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c >>> @@ -0,0 +1,33 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1; >>> + v8 s2f2; >>> +}; >>> + >>> +int foo_s2f2 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f2[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f2 (3)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c >>> new file mode 100644 >>> index 0000000..f273d58 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c >>> @@ -0,0 +1,27 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v16 __attribute__ ((vector_size (16))); >>> + >>> +struct S1 >>> +{ >>> + v16 s1f1; >>> +}; >>> + >>> +int foo_s1f1 (int i) >>> +{ >>> + register struct S1 b asm ("xmm0"); >>> + return b.s1f1[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s1f1 (-1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c >>> new file mode 100644 >>> index 0000000..aa8f7b9 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c >>> @@ -0,0 +1,24 @@ >>> +/* { dg-do run } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v16 __attribute__ ((vector_size (16))); >>> + >>> +struct S1 >>> +{ >>> + v16 s1f1; >>> +}; >>> + >>> +int foo_s1f1 (int i) >>> +{ >>> + register struct S1 b asm ("xmm0"); >>> + return b.s1f1[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s1f1 (0)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c >>> new file mode 100644 >>> index 0000000..3d0c9b2 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c >>> @@ -0,0 +1,27 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v16 __attribute__ ((vector_size (16))); >>> + >>> +struct S1 >>> +{ >>> + v16 s1f1; >>> +}; >>> + >>> +int foo_s1f1 (int i) >>> +{ >>> + register struct S1 b asm ("xmm0"); >>> + return b.s1f1[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s1f1 (7)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c >>> new file mode 100644 >>> index 0000000..e81b942 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c >>> @@ -0,0 +1,31 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S2 >>> +{ >>> + v8 s2f2; >>> + int* f3; >>> +}; >>> + >>> +int foo (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + int k = 5; >>> + b.f3 = &k; >>> + b.f3 = b.f3 + i; >>> + return *b.f3; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo (-1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c >>> new file mode 100644 >>> index 0000000..4b1f1ac >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c >>> @@ -0,0 +1,28 @@ >>> +/* { dg-do run } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S2 >>> +{ >>> + v8 s2f2; >>> + int* f3; >>> +}; >>> + >>> +int foo (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + int k = 5; >>> + b.f3 = &k; >>> + b.f3 = b.f3 + i; >>> + return *b.f3; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo (0)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c >>> new file mode 100644 >>> index 0000000..e95e68f >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c >>> @@ -0,0 +1,31 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S2 >>> +{ >>> + v8 s2f2; >>> + int* f3; >>> +}; >>> + >>> +int foo (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + int k = 5; >>> + b.f3 = &k; >>> + b.f3 = b.f3 + i; >>> + return *b.f3; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo (1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c >>> new file mode 100644 >>> index 0000000..201b62d >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-lbv.c >>> @@ -0,0 +1,32 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1[2]; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1[0].s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (-1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c >>> new file mode 100644 >>> index 0000000..f94a879 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-nov.c >>> @@ -0,0 +1,30 @@ >>> +/* { dg-do run } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1[2]; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1[0].s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c >>> new file mode 100644 >>> index 0000000..6ab981d >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-1-ubv.c >>> @@ -0,0 +1,32 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1[2]; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1[0].s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (4)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c >>> new file mode 100644 >>> index 0000000..cc58e8a >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-lbv.c >>> @@ -0,0 +1,32 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1[2]; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1[1].s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (-1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c >>> new file mode 100644 >>> index 0000000..5898c3b >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-nov.c >>> @@ -0,0 +1,30 @@ >>> +/* { dg-do run } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1[2]; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1[1].s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (1)); >>> + return 0; >>> +} >>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c >>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c >>> new file mode 100644 >>> index 0000000..2910795 >>> --- /dev/null >>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-5-2-ubv.c >>> @@ -0,0 +1,32 @@ >>> +/* { dg-do run } */ >>> +/* { dg-shouldfail "bounds violation" } */ >>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>> + >>> + >>> +#define SHOULDFAIL >>> + >>> +#include "mpx-check.h" >>> + >>> +typedef int v8 __attribute__ ((vector_size (8))); >>> + >>> +struct S1 >>> +{ >>> + v8 s1f; >>> +}; >>> + >>> +struct S2 >>> +{ >>> + struct S1 s2f1[2]; >>> +}; >>> + >>> +int foo_s2f1 (int i) >>> +{ >>> + register struct S2 b asm ("xmm0"); >>> + return b.s2f1[1].s1f[i]; >>> +} >>> + >>> +int mpx_test (int argc, const char **argv) >>> +{ >>> + printf ("%d\n", foo_s2f1 (4)); >>> + return 0; >>> +} >>> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c >>> index b1ff218..6a48a55 100644 >>> --- a/gcc/tree-chkp.c >>> +++ b/gcc/tree-chkp.c >>> @@ -679,6 +679,46 @@ chkp_erase_completed_bounds (void) >>> chkp_completed_bounds_set = new hash_set<tree>; >>> } >>> >>> +/* This function is used to provide a base address for >>> + chkp_get_hard_register_fake_addr_expr. */ >>> +static tree >>> +chkp_get_hard_register_var_fake_base_address () >>> +{ >>> + tree base = fold_convert (ptr_type_node, integer_zero_node); >>> + unsigned HOST_WIDE_INT offset = 1 << (TYPE_PRECISION (ptr_type_node) - >>> 1); >>> + return fold_build_pointer_plus_hwi (base, offset); >>> +} >>> + >>> +/* If we check bounds for a hard register variable, we cannot >>> + use its address - it is illegal, so instead of that we use >>> + this fake value. */ >>> +static tree >>> +chkp_get_hard_register_fake_addr_expr (tree obj) >>> +{ >>> + tree addr = chkp_get_hard_register_var_fake_base_address (); >>> + tree outer = obj; >>> + while (TREE_CODE (outer) == COMPONENT_REF || TREE_CODE (outer) == >>> ARRAY_REF) >>> + { >>> + if (TREE_CODE (outer) == COMPONENT_REF) >>> + { >>> + addr = fold_build_pointer_plus (addr, >>> + component_ref_field_offset (outer)); >>> + outer = TREE_OPERAND (outer, 0); >>> + } >>> + else if (TREE_CODE (outer) == ARRAY_REF) >>> + { >>> + tree indx = fold_convert(size_type_node, TREE_OPERAND(outer, 1)); >>> + tree offset = size_binop (MULT_EXPR, >>> + array_ref_element_size (outer), indx); >>> + addr = fold_build_pointer_plus (addr, offset); >>> + outer = get_base_address (outer); >> >> Hi! >> >> I don't think get_base_address is what you want here because it goes to >> the most inner base. >> >>> + } >>> + } >>> + gcc_assert (VAR_P (outer) && DECL_HARD_REGISTER (outer)); >>> + >>> + return addr; >>> +} >>> + >>> /* Mark BOUNDS associated with PTR as incomplete. */ >>> static void >>> chkp_register_incomplete_bounds (tree bounds, tree ptr) >>> @@ -1044,6 +1084,18 @@ chkp_add_modification_to_stmt_list (tree lhs, >>> static tree >>> chkp_build_addr_expr (tree obj) >>> { >>> + /* We first check whether it is a "hard reg case". */ >>> + tree outer = obj; >>> + while (TREE_CODE (outer) == COMPONENT_REF >>> + || TREE_CODE (outer) == ARRAY_REF) >>> + if (TREE_CODE (outer) == COMPONENT_REF) >>> + outer = TREE_OPERAND (outer, 0); >>> + else >>> + outer = get_base_address (outer); >> >> And here simple call to get_base_address might replace the whole loop. >> >>> + if (VAR_P (outer) && DECL_HARD_REGISTER (outer)) >>> + return chkp_get_hard_register_fake_addr_expr (obj); >>> + >>> + /* If not - return regular ADDR_EXPR. */ >>> return TREE_CODE (obj) == TARGET_MEM_REF >>> ? tree_mem_ref_addr (ptr_type_node, obj) >>> : build_fold_addr_expr (obj); >>> @@ -3442,6 +3494,13 @@ chkp_parse_array_and_component_ref (tree node, tree >>> *ptr, >>> || TREE_CODE (var) == SSA_NAME); >>> >>> *ptr = chkp_build_addr_expr (var); >>> + >>> + /* For hard register cases chkp_build_addr_expr returns INTEGER_CST >>> + and later on chkp_find_bounds will fail to find proper bounds. >>> + In order to avoid that, we find/create bounds right aways using >>> + the var itself. */ >>> + if (DECL_HARD_REGISTER (var)) >>> + *bounds = chkp_find_bounds (var, iter); >> >> Current semantics of this call is to get bounds for the pointer read from >> var. >> I know we never get here fo pointer vars but still... >> >> I propose to just call chkp_make_addressed_object_bounds here instead of >> chkp_find_bounds to avoid this non-intuitive interpretation of non-pointer >> hardreg variable in chkp_find_bounds_1. >> >> BTW what if we have a structure with a pointer field or vector of pointers? >> If we read this pointer then we might have some fun trying to find its >> bounds. >> Let's make a test! :) >> >> Also what code do we produce now? Do we create static bounds variable >> to hold fake bounds of hard reg variable? Is it initialized statically >> or dynamically? >> >>> } >>> >>> /* In this loop we are trying to find a field access >>> @@ -3639,6 +3698,8 @@ chkp_find_bounds_1 (tree ptr, tree ptr_src, >>> gimple_stmt_iterator *iter) >>> addr = chkp_build_addr_expr (ptr_src); >>> bounds = chkp_build_bndldx (addr, ptr, iter); >>> } >>> + else if (VAR_P (ptr) && DECL_HARD_REGISTER (ptr)) >>> + bounds = chkp_make_addressed_object_bounds (ptr_src, iter); >>> else >>> bounds = chkp_get_nonpointer_load_bounds (); >>> break; >>> >>> >>> >>> >>> >>> As before, the following added testcases fail because of PR80270: >> >> That makes hard to confirm patch correctness. Please at least check >> GIMPLE for some of these tests are produced correctly by chkp phase. >> >> Overall this version looks much simpler and better. New MPX feature >> to catch non-memory bounds violation is almost done! >> >> Thanks, >> Ilya >> >>> >>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 (internal compiler >>> error) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O3 -g (internal compiler >>> error) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O3 -g (test for excess >>> errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto >>> -fno-use-linker-plugin -flto-partition=none (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto >>> -fno-use-linker-plugin -flto-partition=none (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto >>> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-1-ubv.c -O2 -flto >>> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 (internal compiler >>> error) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O3 -g (internal compiler >>> error) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O3 -g (test for excess >>> errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto >>> -fno-use-linker-plugin -flto-partition=none (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto >>> -fno-use-linker-plugin -flto-partition=none (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto >>> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-3-2-nov.c -O2 -flto >>> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-4-lbv.c -O0 (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-4-lbv.c -O0 (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-4-nov.c -O0 (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-4-nov.c -O0 (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-4-ubv.c -O0 (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-4-ubv.c -O0 (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 (internal compiler >>> error) >>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O3 -g (internal compiler >>> error) >>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O3 -g (test for excess >>> errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto >>> -fno-use-linker-plugin -flto-partition=none (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto >>> -fno-use-linker-plugin -flto-partition=none (test for excess errors) >>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto >>> -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) >>> FAIL: gcc.target/i386/mpx/hard-reg-5-2-nov.c -O2 -flto >>> -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) >>> >>> hard-reg-4-* looks suspicious to me. May be we need to handle that >>> case differently, but it is hard to say because of the ICE now. >>> >>> >>> 2017-04-10 23:21 GMT+02:00 Ilya Enkovich <enkovich....@gmail.com>: >>>> 2017-04-02 23:52 GMT+03:00 Alexander Ivchenko <aivch...@gmail.com>: >>>>> Hi, >>>>> >>>>> Here is the patch that roughly follows your idea. >>>>> Some comments: >>>>> >>>>> - There are more cases than array_ref overflow. We need to take care >>>>> of component_ref and both underflows/overflows are possible >>>>> - I could not make it work with "0" as a fake address, because then >>>>> catching lower bounds violation is getting hard at O2 and above. E.g. >>>>> consider this: >>>>> >>>>> 0x00000000004005f8 <+8>: bndmk 0x7(%rax),%bnd0 >>>>> 0x00000000004005fd <+13>: mov $0x400734,%edi >>>>> => 0x0000000000400602 <+18>: bndcl 0xfffffffffffffffc,%bnd0 >>>>> (gdb) p $bnd0 >>>>> $1 = {lbound = 0x0, ubound = 0x7} : size 8 >>>>> 0x000000000040060b <+27>: callq 0x400500 <printf@plt> >>>>> >>>>> - bndcu is removed as not necessary and underflowed access is not >>>>> caught. I used another fake value for lower bound address, which is >>>>> 2^(bitness - 1) >>>> >>>> Hi, >>>> >>>> Looks like CHKP optimizations don't let us catch cases when pointer >>>> arithmetc overflows. Using any fake value doesn't guarantee you don't >>>> have overflow. >>>> >>>> This overoptimization is definately a separate issue. It should be easy >>>> to write a test where usage of a huge index in array causes >>>> uncought bounds violation because of removed bndcl/bndcu. You should >>>> file a bug for that. >>>> >>>> If we don't try to work around overflow issues in this patch then using 0 >>>> should be more efficient because it allows you to always use bndcu only >>>> (you just can't violate zero lower bound). >>>> >>>> BTW please don't forget ChangeLogs for your patches. >>>> >>>>> >>>>> - hard-reg-3-[1,2]* tests fail with ICE right now because of PR80270. >>>>> I will mark them as XFAIL if the patch is approved and the mentioned >>>>> bug is not fixed >>>>> >>>>> >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c >>>>> new file mode 100644 >>>>> index 0000000..319e1ec >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-lbv.c >>>>> @@ -0,0 +1,21 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v16 __attribute__((vector_size(16))); >>>>> + >>>>> +int foo(int i) { >>>>> + register v16 u asm("xmm0"); >>>>> + return u[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo (-1)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c >>>>> new file mode 100644 >>>>> index 0000000..3c6d39a >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-nov.c >>>>> @@ -0,0 +1,18 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v16 __attribute__((vector_size(16))); >>>>> + >>>>> +int foo (int i) { >>>>> + register v16 u asm ("xmm0"); >>>>> + return u[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo (3)); >>>>> + printf ("%d\n", foo (0)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c >>>>> new file mode 100644 >>>>> index 0000000..7fe76c4 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-2-ubv.c >>>>> @@ -0,0 +1,21 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v16 __attribute__((vector_size(16))); >>>>> + >>>>> +int foo (int i) { >>>>> + register v16 u asm ("xmm0"); >>>>> + return u[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo (5)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c >>>>> new file mode 100644 >>>>> index 0000000..7e4451f >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-lbv.c >>>>> @@ -0,0 +1,33 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v8 s1f; >>>>> +}; >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + struct S1 s2f1; >>>>> + v8 s2f2; >>>>> +}; >>>>> + >>>>> +int foo_s2f1 (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + return b.s2f1.s1f[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s2f1 (-1)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c >>>>> new file mode 100644 >>>>> index 0000000..73bd7fb >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-nov.c >>>>> @@ -0,0 +1,30 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v8 s1f; >>>>> +}; >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + struct S1 s2f1; >>>>> + v8 s2f2; >>>>> +}; >>>>> + >>>>> +int foo_s2f1 (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + return b.s2f1.s1f[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s2f1 (0)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c >>>>> new file mode 100644 >>>>> index 0000000..166b6b9 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-1-ubv.c >>>>> @@ -0,0 +1,33 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v8 s1f; >>>>> +}; >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + struct S1 s2f1; >>>>> + v8 s2f2; >>>>> +}; >>>>> + >>>>> +int foo_s2f1 (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + return b.s2f1.s1f[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s2f1 (3)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c >>>>> new file mode 100644 >>>>> index 0000000..7820c2f >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-lbv.c >>>>> @@ -0,0 +1,33 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v8 s1f; >>>>> +}; >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + struct S1 s2f1; >>>>> + v8 s2f2; >>>>> +}; >>>>> + >>>>> +int foo_s2f2 (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + return b.s2f2[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s2f2 (-1)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c >>>>> new file mode 100644 >>>>> index 0000000..0816e58 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-nov.c >>>>> @@ -0,0 +1,30 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v8 s1f; >>>>> +}; >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + struct S1 s2f1; >>>>> + v8 s2f2; >>>>> +}; >>>>> + >>>>> +int foo_s2f2 (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + return b.s2f2[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s2f2 (0)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c >>>>> new file mode 100644 >>>>> index 0000000..94261a7 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-2-ubv.c >>>>> @@ -0,0 +1,33 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v8 s1f; >>>>> +}; >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + struct S1 s2f1; >>>>> + v8 s2f2; >>>>> +}; >>>>> + >>>>> +int foo_s2f2 (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + return b.s2f2[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s2f2 (3)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c >>>>> new file mode 100644 >>>>> index 0000000..f273d58 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-lbv.c >>>>> @@ -0,0 +1,27 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v16 __attribute__ ((vector_size (16))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v16 s1f1; >>>>> +}; >>>>> + >>>>> +int foo_s1f1 (int i) >>>>> +{ >>>>> + register struct S1 b asm ("xmm0"); >>>>> + return b.s1f1[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s1f1 (-1)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c >>>>> new file mode 100644 >>>>> index 0000000..aa8f7b9 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-nov.c >>>>> @@ -0,0 +1,24 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v16 __attribute__ ((vector_size (16))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v16 s1f1; >>>>> +}; >>>>> + >>>>> +int foo_s1f1 (int i) >>>>> +{ >>>>> + register struct S1 b asm ("xmm0"); >>>>> + return b.s1f1[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s1f1 (0)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c >>>>> new file mode 100644 >>>>> index 0000000..3d0c9b2 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-3-ubv.c >>>>> @@ -0,0 +1,27 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v16 __attribute__ ((vector_size (16))); >>>>> + >>>>> +struct S1 >>>>> +{ >>>>> + v16 s1f1; >>>>> +}; >>>>> + >>>>> +int foo_s1f1 (int i) >>>>> +{ >>>>> + register struct S1 b asm ("xmm0"); >>>>> + return b.s1f1[i]; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo_s1f1 (7)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c >>>>> new file mode 100644 >>>>> index 0000000..e81b942 >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-lbv.c >>>>> @@ -0,0 +1,31 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + v8 s2f2; >>>>> + int* f3; >>>>> +}; >>>>> + >>>>> +int foo (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + int k = 5; >>>>> + b.f3 = &k; >>>>> + b.f3 = b.f3 + i; >>>>> + return *b.f3; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo (-1)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c >>>>> new file mode 100644 >>>>> index 0000000..4b1f1ac >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-nov.c >>>>> @@ -0,0 +1,28 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + v8 s2f2; >>>>> + int* f3; >>>>> +}; >>>>> + >>>>> +int foo (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + int k = 5; >>>>> + b.f3 = &k; >>>>> + b.f3 = b.f3 + i; >>>>> + return *b.f3; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo (0)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c >>>>> b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c >>>>> new file mode 100644 >>>>> index 0000000..e95e68f >>>>> --- /dev/null >>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/hard-reg-4-ubv.c >>>>> @@ -0,0 +1,31 @@ >>>>> +/* { dg-do run } */ >>>>> +/* { dg-shouldfail "bounds violation" } */ >>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>> + >>>>> + >>>>> +#define SHOULDFAIL >>>>> + >>>>> +#include "mpx-check.h" >>>>> + >>>>> +typedef int v8 __attribute__ ((vector_size (8))); >>>>> + >>>>> +struct S2 >>>>> +{ >>>>> + v8 s2f2; >>>>> + int* f3; >>>>> +}; >>>>> + >>>>> +int foo (int i) >>>>> +{ >>>>> + register struct S2 b asm ("xmm0"); >>>>> + int k = 5; >>>>> + b.f3 = &k; >>>>> + b.f3 = b.f3 + i; >>>>> + return *b.f3; >>>>> +} >>>>> + >>>>> +int mpx_test (int argc, const char **argv) >>>>> +{ >>>>> + printf ("%d\n", foo (1)); >>>>> + return 0; >>>>> +} >>>>> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c >>>>> index b1ff218..15c0da6 100644 >>>>> --- a/gcc/tree-chkp.c >>>>> +++ b/gcc/tree-chkp.c >>>>> @@ -679,6 +679,17 @@ chkp_erase_completed_bounds (void) >>>>> chkp_completed_bounds_set = new hash_set<tree>; >>>>> } >>>>> >>>>> +/* If we check bounds for a hard register variable, we cannot >>>>> + use its address - it is illegal, so instead of that we use >>>>> + this fake value. */ >>>>> +static tree >>>>> +chkp_get_hard_register_var_fake_address () >>>>> +{ >>>>> + tree base = fold_convert (ptr_type_node, integer_zero_node); >>>>> + unsigned HOST_WIDE_INT offset = 1 << (TYPE_PRECISION (ptr_type_node) - >>>>> 1); >>>>> + return fold_build_pointer_plus_hwi (base, offset); >>>>> +} >>>>> + >>>>> /* Mark BOUNDS associated with PTR as incomplete. */ >>>>> static void >>>>> chkp_register_incomplete_bounds (tree bounds, tree ptr) >>>>> @@ -1040,10 +1051,24 @@ chkp_add_modification_to_stmt_list (tree lhs, >>>>> stmts->avail--; >>>>> } >>>>> >>>>> -/* Build and return ADDR_EXPR for specified object OBJ. */ >>>>> +/* Build and return ADDR_EXPR for specified object OBJ. >>>>> + There is a special case for which we cannot return >>>>> + ADDR_EXPR - if the object is declared to be placed >>>>> + on a fixed hard register - in this case we cannot >>>>> + take its address, so we use the object itself. The >>>>> + caller of this function must be aware of that and >>>>> + use proper checks if necessary. */ >>>> >>>> I don't follow the idea of this change. >>>> >>>> If we want to use fake address for register vars then why not to >>>> return this fake value by this function? In case of accessing a >>>> component of register var we should return fake value + required >>>> offset then. >>>> >>>>> static tree >>>>> chkp_build_addr_expr (tree obj) >>>>> { >>>>> + /* We first check whether it is a "hard reg case". */ >>>>> + tree outer = obj; >>>>> + while (TREE_CODE (outer) == COMPONENT_REF) >>>>> + outer = TREE_OPERAND (outer, 0); >>>> >>>> What about ARRAY_REF? Probably get_base_address is what you need. >>>> >>>>> + if (VAR_P (outer) && DECL_HARD_REGISTER (outer)) >>>>> + return obj; >>>>> + >>>>> + /* If not - return regular ADDR_EXPR. */ >>>>> return TREE_CODE (obj) == TARGET_MEM_REF >>>>> ? tree_mem_ref_addr (ptr_type_node, obj) >>>>> : build_fold_addr_expr (obj); >>>>> @@ -3170,6 +3195,11 @@ chkp_get_bounds_for_decl_addr (tree decl) >>>>> gcc_assert (VAR_P (decl)); >>>>> bounds = chkp_generate_extern_var_bounds (decl); >>>>> } >>>>> + else if (VAR_P (decl) && DECL_HARD_REGISTER (decl)) >>>>> + { >>>>> + tree lb = chkp_get_hard_register_var_fake_address (); >>>>> + bounds = chkp_make_bounds(lb, DECL_SIZE_UNIT (decl), NULL, false); >>>>> + } >>>>> else >>>>> { >>>>> tree lb = chkp_build_addr_expr (decl); >>>>> @@ -3351,6 +3381,8 @@ chkp_narrow_bounds_to_field (tree bounds, tree >>>>> component, >>>>> tree field_ptr = chkp_build_addr_expr (component); >>>>> tree field_bounds; >>>>> >>>>> + if (!BOUNDED_P (field_ptr)) >>>>> + field_ptr = chkp_get_hard_register_var_fake_address (); >>>> >>>> This gives you fake pointer instead of fake pointer + offset. No? >>>> >>>>> field_bounds = chkp_make_bounds (field_ptr, size, iter, false); >>>>> >>>>> return chkp_intersect_bounds (field_bounds, bounds, iter); >>>>> @@ -3639,6 +3671,8 @@ chkp_find_bounds_1 (tree ptr, tree ptr_src, >>>>> gimple_stmt_iterator *iter) >>>>> addr = chkp_build_addr_expr (ptr_src); >>>>> bounds = chkp_build_bndldx (addr, ptr, iter); >>>>> } >>>>> + else if (VAR_P (ptr) && DECL_HARD_REGISTER (ptr)) >>>>> + bounds = chkp_make_addressed_object_bounds (ptr_src, iter); >>>> >>>> I don't get what this piece of code is for. >>>> >>>>> else >>>>> bounds = chkp_get_nonpointer_load_bounds (); >>>>> break; >>>>> @@ -4031,7 +4065,19 @@ chkp_process_stmt (gimple_stmt_iterator *iter, >>>>> tree node, >>>>> addr_first, >>>>> byte_position (field)); >>>>> } >>>>> - else >>>>> + else if (VAR_P (ptr) && DECL_HARD_REGISTER (ptr)) >>>>> + { >>>>> + gcc_assert (TREE_CODE (node) == ARRAY_REF >>>>> + || TREE_CODE (node) == COMPONENT_REF); >>>> >>>> This may never hit because this code is in a switch block filtering >>>> node to ARRAY_REF and COMPONENT_REF already. >>>> >>>>> + >>>>> + tree base = chkp_get_hard_register_var_fake_address (); >>>>> + tree indx = fold_convert_loc (loc, >>>>> + size_type_node, >>>>> + TREE_OPERAND (node, 1)); >>>> >>>> Code looks like it expects ARRAY_REF only but COMPONENT_REF >>>> is also possible. >>>> >>>>> + tree offset = size_binop_loc (loc, MULT_EXPR, size, indx); >>>> >>>> 'size' here holds a size of memory access, not size of array element. >>>> >>>> Overall it looks like all you need is a proper fix in chkp_build_addr_expr >>>> to use fake value when required. Many (all?) other changes might just >>>> go away then. >>>> >>>> Thanks, >>>> Ilya >>>> >>>>> + addr_first = fold_build_pointer_plus_loc (loc, base, offset); >>>>> + } >>>>> + else >>>>> addr_first = chkp_build_addr_expr (node); >>>>> } >>>>> break; >>>>> >>>>> 2017-03-23 20:57 GMT+01:00 Ilya Enkovich <enkovich....@gmail.com>: >>>>>> 2017-03-23 17:18 GMT+03:00 Alexander Ivchenko <aivch...@gmail.com>: >>>>>>> Hi, >>>>>>> >>>>>>> The patch below attempts to fix the PR. I checked that it did not >>>>>>> break any of mpx.exp tests, but I did not run the full testing yet. >>>>>>> Would like to know whether this approach is generally correct or not. >>>>>>> >>>>>>> The issue is that we have the hard reg vector variable: >>>>>>> >>>>>>> typedef int U __attribute__ ((vector_size (16))); >>>>>>> register U u asm("xmm0"); >>>>>>> >>>>>>> and chkp tries to instrument access to it: >>>>>>> >>>>>>> return u[i]; >>>>>>> >>>>>>> by doing that: >>>>>>> >>>>>>> __bound_tmp.0_4 = __builtin_ia32_bndmk (&u, 16); >>>>>>> >>>>>>> However, you cannot take an address of a register variable (in fact if >>>>>>> you do that, the compiler will give you "address of register variable >>>>>>> āuā requested" error), so expand, sensibly, gives an ICE on on &u >>>>>>> here. I believe that if there is no pointers, pointer bounds checker >>>>>>> shouldn't get involved into that business. What do you think? >>>>>> >>>>>> Hi! >>>>>> >>>>>> I think with this patch I can call foo with any index and thus access >>>>>> some random stack slot. The first thing we should answer is 'do we >>>>>> want to catch array index overflows in such cases'? If we want to (and >>>>>> this looks reasonable thing to do because it prevents invalid memory >>>>>> accesses) then this patch doesn't resolve the problem. >>>>>> >>>>>> I'm not sure it can affect the patch, but please consider more complex >>>>>> cases. E.g.: >>>>>> >>>>>> typedef int v8 __attribute__ ((vector_size(8))); >>>>>> >>>>>> struct U { >>>>>> v8 a; >>>>>> v8 b; >>>>>> }; >>>>>> >>>>>> int >>>>>> foo (int i) >>>>>> { >>>>>> register struct U u asm ("xmm0"); >>>>>> return u.b[i]; >>>>>> } >>>>>> >>>>>> One way to catch overflow in such cases might be to use some fake >>>>>> pointer value (e.g. 0) for such not addressible variable. This fake value >>>>>> would be used as base for memory access and as lower bound. I don't >>>>>> see other cases except array_ref overflow check where such value >>>>>> might be used. So this fake value will not be passed somewhere and >>>>>> will not be stored to Bounds Table. >>>>>> >>>>>> Thanks, >>>>>> Ilya >>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c >>>>>>> index 75caf83..e39ec9a 100644 >>>>>>> --- a/gcc/tree-chkp.c >>>>>>> +++ b/gcc/tree-chkp.c >>>>>>> @@ -3383,6 +3383,7 @@ chkp_parse_array_and_component_ref (tree node, >>>>>>> tree *ptr, >>>>>>> tree comp_to_narrow = NULL_TREE; >>>>>>> tree last_comp = NULL_TREE; >>>>>>> bool array_ref_found = false; >>>>>>> + bool is_register_var = false; >>>>>>> tree *nodes; >>>>>>> tree var; >>>>>>> int len; >>>>>>> @@ -3440,6 +3441,9 @@ chkp_parse_array_and_component_ref (tree node, >>>>>>> tree *ptr, >>>>>>> || TREE_CODE (var) == STRING_CST >>>>>>> || TREE_CODE (var) == SSA_NAME); >>>>>>> >>>>>>> + if (VAR_P (var) && DECL_HARD_REGISTER (var)) >>>>>>> + is_register_var = true; >>>>>>> + >>>>>>> *ptr = chkp_build_addr_expr (var); >>>>>>> } >>>>>>> >>>>>>> @@ -3455,7 +3459,11 @@ chkp_parse_array_and_component_ref (tree node, >>>>>>> tree *ptr, >>>>>>> >>>>>>> if (TREE_CODE (var) == ARRAY_REF) >>>>>>> { >>>>>>> - *safe = false; >>>>>>> + // Mark it as unsafe, unless the array being accessed >>>>>>> + // has been explicitly placed on a register: in this >>>>>>> + // case we cannot take a pointer of this variable, >>>>>>> + // so we don't instrument the access. >>>>>>> + *safe = is_register_var; >>>>>>> array_ref_found = true; >>>>>>> if (flag_chkp_narrow_bounds >>>>>>> && !flag_chkp_narrow_to_innermost_arrray >>>>>>> @@ -4001,6 +4009,19 @@ chkp_process_stmt (gimple_stmt_iterator *iter, >>>>>>> tree node, >>>>>>> bool bitfield; >>>>>>> tree elt; >>>>>>> >>>>>>> + { >>>>>>> + // We don't instrument accesses to arrays that >>>>>>> + // are explicitely assigned to hard registers. >>>>>>> + HOST_WIDE_INT bitsize, bitpos; >>>>>>> + tree base, offset; >>>>>>> + machine_mode mode; >>>>>>> + int unsignedp, reversep, volatilep = 0; >>>>>>> + base = get_inner_reference (node, &bitsize, &bitpos, &offset, >>>>>>> &mode, >>>>>>> + &unsignedp, &reversep, >>>>>>> &volatilep); >>>>>>> + if (VAR_P (base) && DECL_HARD_REGISTER (base)) >>>>>>> + safe = true; >>>>>>> + } >>>>>>> + >>>>>>> if (safe) >>>>>>> { >>>>>>> /* We are not going to generate any checks, so do not >>>>>>> >>>>>>> diff --git a/gcc/testsuite/gcc.target/i386/mpx/pr79990.c >>>>>>> b/gcc/testsuite/gcc.target/i386/mpx/pr79990.c >>>>>>> new file mode 100644 >>>>>>> index 0000000..a27734d >>>>>>> --- /dev/null >>>>>>> +++ b/gcc/testsuite/gcc.target/i386/mpx/pr79990.c >>>>>>> @@ -0,0 +1,18 @@ >>>>>>> +/* { dg-do compile } */ >>>>>>> +/* { dg-options "-fcheck-pointer-bounds -mmpx" } */ >>>>>>> + >>>>>>> +typedef int U __attribute__ ((vector_size (16))); >>>>>>> + >>>>>>> +int >>>>>>> +foo (int i) >>>>>>> +{ >>>>>>> +#if __SSE2__ >>>>>>> + register >>>>>>> +#endif >>>>>>> + U u >>>>>>> +#if __SSE2__ >>>>>>> + asm ("xmm0") >>>>>>> +#endif >>>>>>> + ; >>>>>>> + return u[i]; >>>>>>> +} >>>>>>> >>>>>>> regards, >>>>>>> Alexander