[07/10] tree-object-size: Handle function parameters

Message ID 20211109190137.1107736-8-siddhesh@gotplt.org
State Superseded
Headers
Series __builtin_dynamic_object_size |

Commit Message

Siddhesh Poyarekar Nov. 9, 2021, 7:01 p.m. UTC
  Handle hints provided by __attribute__ ((access (...))) to compute
dynamic sizes for objects.

gcc/ChangeLog:

	* tree-object-size.c: Include tree-dfa.h.
	(parm_object_size): New function.
	(collect_object_sizes_for): Call it.

gcc/testsuite/ChangeLog:

	* gcc.dg/builtin-dynamic-object-size-0.c (test_parmsz_simple):
	New function.
	(main): Call it.

Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
---
 .../gcc.dg/builtin-dynamic-object-size-0.c    | 10 ++++
 gcc/tree-object-size.c                        | 55 ++++++++++++++++++-
 2 files changed, 64 insertions(+), 1 deletion(-)
  

Patch

diff --git a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
index ddedf6a49bd..80896d54693 100644
--- a/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
+++ b/gcc/testsuite/gcc.dg/builtin-dynamic-object-size-0.c
@@ -46,6 +46,13 @@  test_deploop (size_t sz, size_t cond)
   return __builtin_dynamic_object_size (bin, 0);
 }
 
+size_t
+__attribute__ ((access (__read_write__, 1, 2)))
+test_parmsz_simple (void *obj, size_t sz)
+{
+  return __builtin_dynamic_object_size (obj, 0);
+}
+
 unsigned nfails = 0;
 
 #define FAIL() ({ \
@@ -64,6 +71,9 @@  main (int argc, char **argv)
     FAIL ();
   if (test_deploop (128, 129) != 32)
     FAIL ();
+  if (test_parmsz_simple (argv[0], __builtin_strlen (argv[0]) + 1)
+      != __builtin_strlen (argv[0]) + 1)
+    FAIL ();
 
   if (nfails > 0)
     __builtin_abort ();
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c
index 33598ddc91c..5a80432d40c 100644
--- a/gcc/tree-object-size.c
+++ b/gcc/tree-object-size.c
@@ -32,6 +32,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 #include "gimple-iterator.h"
 #include "tree-cfg.h"
+#include "tree-dfa.h"
 #include "stringpool.h"
 #include "attribs.h"
 #include "builtins.h"
@@ -1373,6 +1374,58 @@  phi_dynamic_object_size (struct object_size_info *osi, tree var)
   return res;
 }
 
+/* Find size of an object passed as a parameter to the function.  */
+
+static tree
+parm_object_size (struct object_size_info *osi, tree var)
+{
+  int object_size_type = osi->object_size_type;
+  tree parm = SSA_NAME_VAR (var);
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "Object is a parameter: ");
+      print_generic_expr (dump_file, parm, dump_flags);
+      fprintf (dump_file, " which is %s a pointer type\n",
+	       POINTER_TYPE_P (TREE_TYPE (parm)) ? "" : "not");
+    }
+
+  if (!(object_size_type & OST_DYNAMIC) || !POINTER_TYPE_P (TREE_TYPE (parm)))
+    return expr_object_size (osi, parm);
+
+  /* Look for access attribute.  */
+  rdwr_map rdwr_idx;
+
+  tree fndecl = cfun->decl;
+  const attr_access *access = get_parm_access (rdwr_idx, parm, fndecl);
+  tree typesize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (parm)));
+
+  if (access && access->sizarg != UINT_MAX)
+    {
+      tree fnargs = DECL_ARGUMENTS (fndecl);
+      tree arg = NULL_TREE;
+      unsigned argpos = 0;
+
+      /* Walk through the parameters to pick the size parameter and safely
+	 scale it by the type size.  */
+      for (arg = fnargs; argpos != access->sizarg && arg;
+	   arg = TREE_CHAIN (arg), ++argpos);
+
+      if (arg != NULL_TREE && INTEGRAL_TYPE_P (TREE_TYPE (arg)))
+	{
+	  tree sz = get_or_create_ssa_default_def (cfun, arg);
+	  if (sz != NULL_TREE)
+	    {
+	      sz = fold_convert (sizetype, sz);
+	      if (typesize)
+		sz = size_binop (MULT_EXPR, sz, typesize);
+	      return sz;
+	    }
+	}
+    }
+  return size_unknown (object_size_type);
+}
+
 /* Compute object sizes for VAR.
    For ADDR_EXPR an object size is the number of remaining bytes
    to the end of the object (where what is considered an object depends on
@@ -1483,7 +1536,7 @@  collect_object_sizes_for (struct object_size_info *osi, tree var)
     case GIMPLE_NOP:
       if (SSA_NAME_VAR (var)
 	  && TREE_CODE (SSA_NAME_VAR (var)) == PARM_DECL)
-	res = expr_object_size (osi, SSA_NAME_VAR (var));
+	res = parm_object_size (osi, var);
       else
 	/* Uninitialized SSA names point nowhere.  */
 	res = size_unknown (object_size_type);