This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa mudflap] support variable-length arrays


Hi -

The following patch aims to add support for variable-length arrays
to mudflap instrumentation.  This is unforunately somewhat messy
because of the way VLAs are implemented and the timing of the mudflap
processing passes.  As a "-fdump-tree-all" run shows, VLAs are assigned
their actual base address and size during run time, via a call to
builtin_stack_alloc.  The mudflap1 transform finds such calls that
correspond to VLA decls, and appends afterward matching __mf_register
calls.  Two new test cases poke at this code.

- FChE

2004-01-27  Frank Ch. Eigler  <fche@redhat.com>

	* tree-mudflap.c (mx_register_decls): Support VLAs.
	(mf_xform_derefs_1): Disable checking shortcut for VLAs.
	* c-simplify.c (gimplify_decl_stmt): Add mudflap xref comment.
	* gimplify.c (gimplify_bind_expr): Ditto.

Index: c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.4.88
diff -u -w -s -p -r1.1.4.88 c-simplify.c
--- c-simplify.c	23 Jan 2004 08:49:29 -0000	1.1.4.88
+++ c-simplify.c	27 Jan 2004 22:33:13 -0000
@@ -862,7 +862,8 @@ gimplify_decl_stmt (tree *stmt_p)
 	  tree alloc, size;
 
 	  /* This is a variable-sized decl.  Simplify its size and mark it
-	     for deferred expansion.  */
+	     for deferred expansion.  Note that mudflap depends on the format
+	     of the emitted code: see mx_register_decls().  */
 
 	  size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post);
 	  DECL_DEFER_OUTPUT (decl) = 1;
Index: gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimplify.c,v
retrieving revision 1.1.2.136
diff -u -w -s -p -r1.1.2.136 gimplify.c
--- gimplify.c	23 Jan 2004 08:49:29 -0000	1.1.2.136
+++ gimplify.c	27 Jan 2004 22:33:13 -0000
@@ -794,7 +794,8 @@ gimplify_bind_expr (tree *expr_p, tree *
       tree stack_save, stack_restore;
 
       /* Save stack on entry and restore it on exit.  Add a try_finally
-	 block to achieve this.  */
+	 block to achieve this.  Note that mudflap depends on the
+	 format of the emitted code: see mx_register_decls().  */
       build_stack_save_restore (&stack_save, &stack_restore);
 
       t = build (TRY_FINALLY_EXPR, void_type_node,
Index: tree-mudflap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-mudflap.c,v
retrieving revision 1.1.2.69
diff -u -w -s -p -r1.1.2.69 tree-mudflap.c
--- tree-mudflap.c	19 Jan 2004 20:37:35 -0000	1.1.2.69
+++ tree-mudflap.c	27 Jan 2004 22:33:13 -0000
@@ -573,7 +573,9 @@ mf_xform_derefs_1 (tree_stmt_iterator *i
 	    /* Test for index in range.  Break if not.  */
 	    if (!dom)
 	      break;
-	    if (!TYPE_MIN_VALUE (dom) || !TYPE_MAX_VALUE (dom))
+            if (!TYPE_MIN_VALUE (dom) || !really_constant_p (TYPE_MIN_VALUE (dom)))
+              break;
+            if (!TYPE_MAX_VALUE (dom) || !really_constant_p (TYPE_MAX_VALUE (dom)))
 	      break;
 	    if (tree_int_cst_lt (op1, TYPE_MIN_VALUE (dom))
 		|| tree_int_cst_lt (TYPE_MAX_VALUE (dom), op1))
@@ -729,7 +731,7 @@ static void
 mx_register_decls (tree decl, tree *stmt_list)
 {
   tree finally_stmts = NULL_TREE;
-  tree initially_stmts = NULL_TREE;
+  tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
 
   while (decl != NULL_TREE)
     {
@@ -741,33 +743,98 @@ mx_register_decls (tree decl, tree *stmt
           (! mf_marked_p (decl)) && /* not already processed */
           (TREE_ADDRESSABLE (decl))) /* has address taken */
         {
+          tree size, variable_name;
+          tree unregister_fncall, unregister_fncall_params;
+          tree register_fncall, register_fncall_params;
+
+          if (DECL_DEFER_OUTPUT (decl))
+            {
+              /* Oh no ... it's probably a variable-length array (VLA).
+                 The size and address cannot be computed by merely
+                 looking at the DECL.  See gimplfiy_decl_stmt for the
+                 method by which VLA declarations turn into calls to
+                 BUILT_IN_STACK_ALLOC.  We assume that multiple
+                 VLAs declared later in the same block get allocation 
+                 code later than the others. */
+              tree stack_alloc_call = NULL_TREE;
+
+              while(! tsi_end_p (initially_stmts))
+                {
+                  tree t = tsi_stmt (initially_stmts);
+
+                  tree call = NULL_TREE;
+                  if (TREE_CODE (t) == CALL_EXPR)
+                    call = t;
+                  else if (TREE_CODE (t) == MODIFY_EXPR &&
+                           TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
+                    call = TREE_OPERAND (t, 1);
+                  else if (TREE_CODE (t) == TRY_FINALLY_EXPR)
+                    {
+                      /* We hope that this is the try/finally block sometimes constructed by 
+                         gimplify_bind_expr() for a BIND_EXPR that contains VLAs.  This very
+                         naive recursion appears to be sufficient.  */
+                      initially_stmts = tsi_start (TREE_OPERAND (t, 0));
+                    }
+
+                  if (call != NULL_TREE)
+                    {
+                      if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR &&
+                          TREE_OPERAND (TREE_OPERAND (call, 0), 0) == implicit_built_in_decls [BUILT_IN_STACK_ALLOC])
+                        {
+                          tree stack_alloc_args = TREE_OPERAND (call, 1);
+                          tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args);
+                          tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args));
+                          
+                          if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR &&
+                              TREE_OPERAND (stack_alloc_op1, 0) == decl)
+                            {
+                              /* Got it! */
+                              size = stack_alloc_op2;
+                              stack_alloc_call = call;
+                              /* Advance iterator to point past this allocation call. */
+                              tsi_next (&initially_stmts);
+                              break;
+                            }
+                        }
+                    }
+
+                  tsi_next (&initially_stmts);
+                }
+
+              if (stack_alloc_call == NULL_TREE)
+                {
+                  warning ("mudflap cannot handle variable-sized declaration `%s'",
+                         IDENTIFIER_POINTER (DECL_NAME (decl)));
+                  break;
+                }
+            }
+          else
+            {
+              size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
+            }
+
           /* (& VARIABLE, sizeof (VARIABLE)) */
-          tree unregister_fncall_params =
+          unregister_fncall_params =
             tree_cons (NULL_TREE,
                        convert (ptr_type_node,
                                 mf_mark (build1 (ADDR_EXPR,
                                                  build_pointer_type (TREE_TYPE (decl)),
                                                  decl))),
-                       tree_cons (NULL_TREE,
-                                  convert (size_type_node,
-                                           TYPE_SIZE_UNIT (TREE_TYPE (decl))),
-                                  NULL_TREE));
+                       tree_cons (NULL_TREE, size, NULL_TREE));
           /* __mf_unregister (...) */
-          tree unregister_fncall =
-            build_function_call_expr (mf_unregister_fndecl,
+          unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
                                  unregister_fncall_params);
 
           /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
-          tree variable_name = mf_varname_tree (decl);
-          tree register_fncall_params =
+          variable_name = mf_varname_tree (decl);
+          register_fncall_params =
             tree_cons (NULL_TREE,
                    convert (ptr_type_node,
                             mf_mark (build1 (ADDR_EXPR,
                                              build_pointer_type (TREE_TYPE (decl)),
                                              decl))),
                        tree_cons (NULL_TREE,
-                                  convert (size_type_node,
-                                           TYPE_SIZE_UNIT (TREE_TYPE (decl))),
+                                  size,
                                   tree_cons (NULL_TREE,
                                              build_int_2 (3, 0), /* __MF_TYPE_STACK */
                                              tree_cons (NULL_TREE,
@@ -775,15 +842,20 @@ mx_register_decls (tree decl, tree *stmt
                                                         NULL_TREE))));
 
           /* __mf_register (...) */
-          tree register_fncall =
-            build_function_call_expr (mf_register_fndecl,
+          register_fncall = build_function_call_expr (mf_register_fndecl,
                                  register_fncall_params);
 
           /* Accumulate the two calls.  */
 	  /* ??? Set EXPR_LOCUS.  */
 	  gimplify_stmt (&register_fncall);
 	  gimplify_stmt (&unregister_fncall);
-          append_to_statement_list (register_fncall, &initially_stmts);
+
+          /* Add the __mf_register call at the current appending point.  */
+          if (tsi_end_p (initially_stmts))
+            internal_error ("mudflap ran off end of BIND_EXPR body");
+          tsi_link_before (& initially_stmts, register_fncall, TSI_SAME_STMT);
+
+          /* Accumulate the FINALLY piece. */
           append_to_statement_list (unregister_fncall, &finally_stmts);
 
           mf_mark (decl);
@@ -792,13 +864,6 @@ mx_register_decls (tree decl, tree *stmt
       decl = TREE_CHAIN (decl);
     }
 
-  /* Now process the pending register/unregister calls, if any.  */
-  if (initially_stmts != NULL_TREE)
-    {
-      append_to_statement_list (*stmt_list, &initially_stmts);
-      *stmt_list = initially_stmts;
-    }
-
   /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
   if (finally_stmts != NULL_TREE)
     {



Index: testsuite/libmudflap.c/fail31-frag.c
===================================================================
RCS file: testsuite/libmudflap.c/fail31-frag.c
diff -N testsuite/libmudflap.c/fail31-frag.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/libmudflap.c/fail31-frag.c	27 Jan 2004 22:41:29 -0000
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int h (int i, int j);
+
+int main ()
+{
+  int z = h (4, 10);
+  return 0;
+}
+
+int h (int i, int j)
+{
+  int k[i];
+  k[j] = i;
+  return j;
+}
+
+/* { dg-output "mudflap violation 1.*" } */
+/* { dg-output "Nearby object.*" } */
+/* { dg-output "mudflap object.*\(h\).*k" } */
+/* { dg-do run { xfail *-*-* } } */
Index: testsuite/libmudflap.c/pass45-frag.c
===================================================================
RCS file: testsuite/libmudflap.c/pass45-frag.c
diff -N testsuite/libmudflap.c/pass45-frag.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/libmudflap.c/pass45-frag.c	27 Jan 2004 22:41:29 -0000
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern void h (const char *p, const char *f);
+int
+main (void)
+{
+  h (0, "foo");
+  return 0;
+}
+
+void
+h (const char *p, const char *f)
+{
+  size_t pl = p == NULL ? 0 : strlen (p);
+  size_t fl = strlen (f) + 1;
+  char a[pl + 1 + fl];
+  char *cp = a;
+  char b[pl + 5 + fl * 2];
+  char *cccp = b;
+  if (p != NULL)
+    {
+      cp = memcpy (cp, p, pl);
+      *cp++ = ':';
+    }
+  memcpy (cp, f, fl);
+  strcpy (b, a);
+  puts (a);
+}
+/* { dg-output "foo" } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]