tree-mudflap.c (mf_build_check_statement_for): Reorganize to take check-base and...
authorFrank Ch. Eigler <fche@redhat.com>
Sat, 2 Oct 2004 23:12:49 +0000 (23:12 +0000)
committerFrank Ch. Eigler <fche@gcc.gnu.org>
Sat, 2 Oct 2004 23:12:49 +0000 (23:12 +0000)
2004-10-02  Frank Ch. Eigler  <fche@redhat.com>

* tree-mudflap.c (mf_build_check_statement_for): Reorganize to
take check-base and -limit arguments.
(mf_xform_derefs_1): Reorganize slightly to pass proper base/limit
check ranges for ARRAY_REF and COMPONENT_REF.
(execute_mudflap_fnction_ops, ..._decls): Limit unnecessary
instrumentation.

2004-10-02  Frank Ch. Eigler  <fche@redhat.com>

* testsuite/libmudflap.c/pass50-frag.c, fail33-frag.c, fail34-frag.c:
New tests for proper base/limit checking for aggregates.

From-SVN: r88432

gcc/ChangeLog
gcc/tree-mudflap.c
libmudflap/ChangeLog
libmudflap/testsuite/libmudflap.c/fail33-frag.c [new file with mode: 0644]
libmudflap/testsuite/libmudflap.c/fail34-frag.c [new file with mode: 0644]
libmudflap/testsuite/libmudflap.c/pass50-frag.c [new file with mode: 0644]

index 4f13472..dcdaf70 100644 (file)
@@ -1,3 +1,12 @@
+2004-10-02  Frank Ch. Eigler  <fche@redhat.com>
+
+       * tree-mudflap.c (mf_build_check_statement_for): Reorganize to
+       take check-base and -limit arguments.
+       (mf_xform_derefs_1): Reorganize slightly to pass proper base/limit
+       check ranges for ARRAY_REF and COMPONENT_REF.
+       (execute_mudflap_fnction_ops, ..._decls): Limit unnecessary
+       instrumentation.
+
 2004-10-02  Joseph S. Myers  <jsm@polyomino.org.uk>
 
        * c-objc-common.c (c_tree_printer): Correct description of %E.
index a61a7ad..bc42de7 100644 (file)
@@ -407,7 +407,10 @@ mudflap_init (void)
 static void
 execute_mudflap_function_ops (void)
 {
-  if (mf_marked_p (current_function_decl))
+  /* Don't instrument functions such as the synthetic constructor
+     built during mudflap_finish_file.  */
+  if (mf_marked_p (current_function_decl) ||
+      DECL_ARTIFICIAL (current_function_decl))
     return;
 
   push_gimplify_context ();
@@ -481,7 +484,7 @@ mf_decl_clear_locals (void)
 }
 
 static void
-mf_build_check_statement_for (tree addr, tree size,
+mf_build_check_statement_for (tree base, tree addr, tree limit,
                               block_stmt_iterator *instr_bsi,
                               location_t *locus, tree dirflag)
 {
@@ -494,6 +497,7 @@ mf_build_check_statement_for (tree addr, tree size,
   tree mf_value;
   tree mf_base;
   tree mf_elem;
+  tree mf_limit;
 
   /* We first need to split the current basic block, and start altering
      the CFG.  This allows us to insert the statements we're about to
@@ -557,6 +561,7 @@ mf_build_check_statement_for (tree addr, tree size,
   mf_value = create_tmp_var (ptrtype, "__mf_value");
   mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
   mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
+  mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit");
 
   /* Build: __mf_value = <address expression>.  */
   t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr));
@@ -565,9 +570,16 @@ mf_build_check_statement_for (tree addr, tree size,
   head = tsi_start (t);
   tsi = tsi_last (t);
 
-  /* Build: __mf_base = (uintptr_t)__mf_value.  */
+  /* Build: __mf_base = (uintptr_t) <base address expression>.  */
   t = build (MODIFY_EXPR, void_type_node, mf_base,
-             build1 (NOP_EXPR, mf_uintptr_type, mf_value));
+             convert (mf_uintptr_type, unshare_expr (base)));
+  SET_EXPR_LOCUS (t, locus);
+  gimplify_to_stmt_list (&t);
+  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
+
+  /* Build: __mf_limit = (uintptr_t) <limit address expression>.  */
+  t = build (MODIFY_EXPR, void_type_node, mf_limit,
+             convert (mf_uintptr_type, unshare_expr (limit)));
   SET_EXPR_LOCUS (t, locus);
   gimplify_to_stmt_list (&t);
   tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
@@ -590,7 +602,7 @@ mf_build_check_statement_for (tree addr, tree size,
   /* Quick validity check.
 
      if (__mf_elem->low > __mf_base
-         || (__mf_elem_high < __mf_base + sizeof(T) - 1))
+         || (__mf_elem_high < __mf_limit))
         {
           __mf_check ();
           ... and only if single-threaded:
@@ -607,22 +619,19 @@ mf_build_check_statement_for (tree addr, tree size,
              TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
   t = build (GT_EXPR, boolean_type_node, t, mf_base);
 
-  /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
+  /* Construct '__mf_elem->high < __mf_limit'.
 
      First build:
         1) u <--  '__mf_elem->high'
-        2) v <--  '__mf_base + sizeof (T) - 1'.
+        2) v <--  '__mf_limit'.
 
      Then build 'u <-- (u < v).  */
 
-
   u = build (COMPONENT_REF, mf_uintptr_type,
              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
              TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
 
-  v = convert (mf_uintptr_type,
-               size_binop (MINUS_EXPR, size, size_one_node));
-  v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v));
+  v = mf_limit;
 
   u = build (LT_EXPR, boolean_type_node, u, v);
 
@@ -647,7 +656,7 @@ mf_build_check_statement_for (tree addr, tree size,
      the conditional jump,
 
      if (__mf_elem->low > __mf_base
-         || (__mf_elem_high < __mf_base + sizeof(T) - 1))
+         || (__mf_elem_high < __mf_limit))
 
      The lowered GIMPLE tree representing this code is in the statement
      list starting at 'head'.
@@ -670,8 +679,14 @@ mf_build_check_statement_for (tree addr, tree size,
                                              : *locus),
                  NULL_TREE);
   u = tree_cons (NULL_TREE, dirflag, u);
-  u = tree_cons (NULL_TREE, size, u);
-  u = tree_cons (NULL_TREE, mf_value, u);
+  /* NB: we pass the overall [base..limit] range to mf_check,
+     not the [mf_value..mf_value+size-1] range.  */
+  u = tree_cons (NULL_TREE, 
+                 fold (build (PLUS_EXPR, integer_type_node,
+                              fold (build (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base)),
+                              integer_one_node)),
+                 u);
+  u = tree_cons (NULL_TREE, mf_base, u);
   t = build_function_call_expr (mf_check_fndecl, u);
   gimplify_to_stmt_list (&t);
   head = tsi_start (t);
@@ -701,7 +716,7 @@ static void
 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
                    location_t *locus, tree dirflag)
 {
-  tree type, ptr_type, addr, size, t;
+  tree type, ptr_type, addr, base, size, limit, t;
 
   /* Don't instrument read operations.  */
   if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
@@ -756,12 +771,20 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
         /* If we got here, we couldn't statically the check.  */
         ptr_type = build_pointer_type (type);
         addr = build1 (ADDR_EXPR, ptr_type, t);
+        base = build1 (ADDR_EXPR, ptr_type, op0);
+        limit = fold (build (MINUS_EXPR, mf_uintptr_type,
+                             fold (build2 (PLUS_EXPR, mf_uintptr_type, addr, size)),
+                             integer_one_node));
       }
       break;
 
     case INDIRECT_REF:
       addr = TREE_OPERAND (t, 0);
       ptr_type = TREE_TYPE (addr);
+      base = addr;
+      limit = fold (build (MINUS_EXPR, ptr_type_node,
+                           fold (build (PLUS_EXPR, ptr_type_node, base, size)),
+                           integer_one_node));
       break;
 
     case ARRAY_RANGE_REF:
@@ -798,6 +821,12 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
             ptr_type = build_pointer_type (type);
             addr = build1 (ADDR_EXPR, ptr_type, t);
           }
+
+        /* XXXXXX */
+        base = addr;
+        limit = fold (build (MINUS_EXPR, ptr_type_node,
+                             fold (build (PLUS_EXPR, ptr_type_node, base, size)),
+                             integer_one_node));
       }
       break;
 
@@ -823,6 +852,11 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
         addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
         addr = convert (ptr_type_node, addr);
         addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
+
+        base = addr;
+        limit = fold (build (MINUS_EXPR, ptr_type_node,
+                             fold (build (PLUS_EXPR, ptr_type_node, base, size)),
+                             integer_one_node));
       }
       break;
 
@@ -830,7 +864,7 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
       return;
     }
 
-  mf_build_check_statement_for (addr, size, iter, locus, dirflag);
+  mf_build_check_statement_for (base, addr, limit, iter, locus, dirflag);
 }
 
 static void
@@ -891,7 +925,10 @@ mf_xform_derefs (void)
 static void
 execute_mudflap_function_decls (void)
 {
-  if (mf_marked_p (current_function_decl))
+  /* Don't instrument functions such as the synthetic constructor
+     built during mudflap_finish_file.  */
+  if (mf_marked_p (current_function_decl) ||
+      DECL_ARTIFICIAL (current_function_decl))
     return;
 
   push_gimplify_context ();
index 984e22b..97ab17c 100644 (file)
@@ -1,3 +1,8 @@
+2004-10-02  Frank Ch. Eigler  <fche@redhat.com>
+
+       * testsuite/libmudflap.c/pass50-frag.c, fail33-frag.c, fail34-frag.c:
+       New tests for proper base/limit checking for aggregates.
+
 2004-09-15  Joseph S. Myers  <jsm@polyomino.org.uk>
 
        * testsuite/libmudflap.c/pass35-frag.c: Update expected message.
diff --git a/libmudflap/testsuite/libmudflap.c/fail33-frag.c b/libmudflap/testsuite/libmudflap.c/fail33-frag.c
new file mode 100644 (file)
index 0000000..5f33be7
--- /dev/null
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+
+#define SIZE 16
+
+char b[SIZE];
+char a[SIZE];
+
+int main ()
+{
+  int i, j=0;
+  int a_before_b = (& a[0] < & b[0]);
+  /* Rather than iterating linearly, which would allow loop unrolling
+     and mapping to pointer manipulation, we traverse the "joined"
+     arrays in some random order.  */
+  for (i=0; i<SIZE*2; i++)
+    {
+      k=rand()%(SIZE*2))
+      j += (a_before_b ? a[k] : b[k]);
+    }
+  return j;
+}
+/* { dg-output "mudflap violation 1.*" } */
+/* { dg-output "Nearby object.*" } */
+/* { dg-output "mudflap object.*\[ab\]" } */
+/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/fail34-frag.c b/libmudflap/testsuite/libmudflap.c/fail34-frag.c
new file mode 100644 (file)
index 0000000..f6572b0
--- /dev/null
@@ -0,0 +1,22 @@
+#include <stdlib.h>
+
+struct s
+{
+  int a1[4];
+};
+
+struct s a, b;
+int idx = 7; /* should pass to the next object */
+
+int
+main ()
+{
+  int i, j=0;
+  int a_before_b = (& a < & b);
+  j = (a_before_b ? a.a1[idx] : b.a1[idx]);
+  return j;
+}
+/* { dg-output "mudflap violation 1.*" } */
+/* { dg-output "Nearby object.*" } */
+/* { dg-output "mudflap object.*\[ab\]" } */
+/* { dg-do run { xfail *-*-* } } */
diff --git a/libmudflap/testsuite/libmudflap.c/pass50-frag.c b/libmudflap/testsuite/libmudflap.c/pass50-frag.c
new file mode 100644 (file)
index 0000000..ac9ee09
--- /dev/null
@@ -0,0 +1,29 @@
+#include <stdlib.h>
+
+struct a
+{
+  int a1[5];
+  union
+  {
+    int b1[5];
+    struct
+    {
+      int c1;
+      int c2;
+    } b2[4];
+  } a2[8];
+};
+
+int i1 = 5;
+int i2 = 2;
+int i3 = 6;
+int i4 = 0;
+
+int
+main ()
+{
+  volatile struct a *k = calloc (1, sizeof (struct a));
+  k->a2[i1].b1[i2] = k->a2[i3].b2[i4].c2;
+  free ((void *) k);
+  return 0;
+}