This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [CHKP] Fix for PR79990
- From: Alexander Ivchenko <aivchenk at gmail dot com>
- To: Ilya Enkovich <enkovich dot gnu at gmail dot com>
- Cc: marxin at gcc dot gnu dot org, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 19 Apr 2017 18:48:15 +0200
- Subject: Re: [CHKP] Fix for PR79990
- Authentication-results: sourceware.org; auth=none
- References: <CACysShgnUuetyR-7wAqh6wusBz67k-iVu6VGHzEzVvRvS2QW8Q@mail.gmail.com> <CAMbmDYb79XYn1oqP1qjz=_JFrXd8q=DqtEwTv3RdwWyTjwg30Q@mail.gmail.com> <CACysShiZxAEf1OEHkNGZNxRWW+Wv99OXx-9VcNBQknnLEe6NAA@mail.gmail.com> <CAMbmDYYP-58HA9CXMW+XuP7TWsKEkbwjM=xLYN-jLMqqf0xcUg@mail.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 <aivchenk@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 <aivchenk@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);
+ }
+ }
+ 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);
+ 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);
}
/* 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:
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.gnu@gmail.com>:
> 2017-04-02 23:52 GMT+03:00 Alexander Ivchenko <aivchenk@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.gnu@gmail.com>:
>>> 2017-03-23 17:18 GMT+03:00 Alexander Ivchenko <aivchenk@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