[v6,2/4] tree-object-size: Handle function parameters
Commit Message
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,
test_parmsz_scaled, test_parmsz_unknown): New functions.
(main): Call them. Add new arguments argc and argv.
Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
---
.../gcc.dg/builtin-dynamic-object-size-0.c | 35 +++++++++++-
gcc/tree-object-size.c | 54 ++++++++++++++++++-
2 files changed, 87 insertions(+), 2 deletions(-)
Comments
On Tue, Jan 11, 2022 at 02:27:48PM +0530, Siddhesh Poyarekar wrote:
> 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,
> test_parmsz_scaled, test_parmsz_unknown): New functions.
> (main): Call them. Add new arguments argc and argv.
>
> Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
> + /* Walk through the parameters to pick the size parameter and safely
> + scale it by the type size. */
> + for (arg = fnargs; arg; arg = TREE_CHAIN (arg), ++argpos)
> + {
> + if (argpos == access->sizarg && INTEGRAL_TYPE_P (TREE_TYPE (arg)))
> + {
> + 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);
> + }
> + break;
> + }
> + }
No need for those {}s around the if as body of for, just use
for (arg = fnargs; arg; arg = TREE_CHAIN (arg), ++argpos)
if (argpos == access->sizarg && INTEGRAL_TYPE_P (TREE_TYPE (arg)))
{
...
break;
}
Ok with that change.
Jakub
@@ -34,6 +34,30 @@ test_deploop (size_t sz, size_t cond)
return __builtin_dynamic_object_size (bin, 0);
}
+size_t
+__attribute__ ((access (__read_write__, 1, 2)))
+__attribute__ ((noinline))
+test_parmsz_simple (void *obj, size_t sz)
+{
+ return __builtin_dynamic_object_size (obj, 0);
+}
+
+size_t
+__attribute__ ((access (__read_write__, 1, 2)))
+__attribute__ ((noinline))
+test_parmsz_scaled (int *obj, size_t sz)
+{
+ return __builtin_dynamic_object_size (obj, 0);
+}
+
+size_t
+__attribute__ ((access (__read_write__, 1, 3)))
+__attribute__ ((noinline))
+test_parmsz_unknown (void *obj, void *unknown, size_t sz, int cond)
+{
+ return __builtin_dynamic_object_size (cond ? obj : unknown, 0);
+}
+
unsigned nfails = 0;
#define FAIL() ({ \
@@ -42,7 +66,7 @@ unsigned nfails = 0;
})
int
-main ()
+main (int argc, char **argv)
{
if (test_builtin_malloc_condphi (1) != 32)
FAIL ();
@@ -50,6 +74,15 @@ main ()
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 ();
+ int arr[42];
+ if (test_parmsz_scaled (arr, 42) != sizeof (arr))
+ FAIL ();
+ if (test_parmsz_unknown (argv[0], argv[0], __builtin_strlen (argv[0]) + 1, 0)
+ != -1)
+ FAIL ();
if (nfails > 0)
__builtin_abort ();
@@ -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"
@@ -1443,6 +1444,57 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt)
return reexamine;
}
+/* Find size of an object passed as a parameter to the function. */
+
+static void
+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 (!(object_size_type & OST_DYNAMIC) || !POINTER_TYPE_P (TREE_TYPE (parm)))
+ {
+ expr_object_size (osi, var, parm);
+ return;
+ }
+
+ /* 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)));
+ tree sz = NULL_TREE;
+
+ 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; arg; arg = TREE_CHAIN (arg), ++argpos)
+ {
+ if (argpos == access->sizarg && INTEGRAL_TYPE_P (TREE_TYPE (arg)))
+ {
+ 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);
+ }
+ break;
+ }
+ }
+ }
+ if (!sz)
+ sz = size_unknown (object_size_type);
+
+ object_sizes_set (osi, SSA_NAME_VERSION (var), sz, sz);
+}
+
/* Compute an object size expression for VAR, which is the result of a PHI
node. */
@@ -1620,7 +1672,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)
- expr_object_size (osi, var, SSA_NAME_VAR (var));
+ parm_object_size (osi, var);
else
/* Uninitialized SSA names point nowhere. */
unknown_object_size (osi, var);