[PATCH 05/10] __builtin_dynamic_object_size: Recognize builtin
Siddhesh Poyarekar
siddhesh@gotplt.org
Tue Nov 23 13:53:01 GMT 2021
On 11/23/21 18:11, Jakub Jelinek wrote:
> On Wed, Nov 10, 2021 at 12:31:31AM +0530, Siddhesh Poyarekar wrote:
>> Recognize the __builtin_dynamic_object_size builtin and add paths in the
>> object size path to deal with it, but treat it like
>> __builtin_object_size for now. Also add tests to provide the same
>> testing coverage for the new builtin name.
>>
>> gcc/ChangeLog:
>>
>> * builtins.def (BUILT_IN_DYNAMIC_OBJECT_SIZE): New builtin.
>> * tree-object-size.h (compute_builtin_object_size): Add new
>> argument dynamic.
>> * builtins.c (expand_builtin, fold_builtin_2): Handle it.
>> (fold_builtin_object_size): Handle new builtin and adjust for
>> change to compute_builtin_object_size.
>> * tree-object-size.c: Include builtins.h.
>> (OST_DYNAMIC): New enum value.
>> (compute_builtin_object_size): Add new argument dynamic.
>> (addr_object_size): Adjust.
>> (early_object_sizes_execute_one,
>> dynamic_object_sizes_execute_one): New functions.
>> (object_sizes_execute): Rename insert_min_max_p argument to
>> early. Handle BUILT_IN_DYNAMIC_OBJECT_SIZE and call the new
>
> Two spaces after . instead of just one.
>
>> --- a/gcc/builtins.def
>> +++ b/gcc/builtins.def
>> @@ -972,6 +972,7 @@ DEF_BUILTIN_STUB (BUILT_IN_STRNCMP_EQ, "__builtin_strncmp_eq")
>>
>> /* Object size checking builtins. */
>> DEF_GCC_BUILTIN (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
>> +DEF_GCC_BUILTIN (BUILT_IN_DYNAMIC_OBJECT_SIZE, "dynamic_object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
>
> Are you sure about the omission of CONST_ in there?
> If I do:
> size_t a = __builtin_dynamic_object_size (x, 0);
> size_t b = __builtin_dynamic_object_size (x, 0);
> I'd expect the compiler to perform it just once. While it might actually do
> it eventually after objsz2 pass lowers it, with the above it won't really do
> it. Perhaps const attribute isn't really safe, the function might need to
> read some memory in order to compute the return value, but certainly it will
> not store to any memory, so perhaps
> ATTR_PURE_NOTHROW_LEAF_LIST ?
Thanks, I'll fix this.
>
>> +#define DYNAMIC_OBJECT_SIZE
>
> Why this extra macro?
>
>> +#define __builtin_object_size __builtin_dynamic_object_size
>
>> extern char ax[];
>> +#ifndef DYNAMIC_OBJECT_SIZE
>
> You can #ifndef __builtin_object_size
> instead...
I'll fix this too.
>
>> @@ -371,7 +373,8 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
>> || TREE_CODE (TREE_OPERAND (pt_var, 0)) != SSA_NAME)
>> {
>> compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
>> - object_size_type & ~OST_SUBOBJECT, &sz);
>> + object_size_type & OST_MINIMUM, &sz,
>> + object_size_type & OST_DYNAMIC);
>> }
>> else
>> {
>> @@ -835,9 +838,10 @@ resolve_dependency_loops (struct object_size_info *osi)
>>
>> bool
>> compute_builtin_object_size (tree ptr, int object_size_type,
>> - tree *psize)
>> + tree *psize, bool dynamic)
>> {
>> gcc_assert (object_size_type >= 0 && object_size_type < OST_END);
>> + object_size_type |= dynamic ? OST_DYNAMIC : 0;
>
> What's the advantage of another argument and then merging it with
> object_size_type over just passing object_size_type which will have
> all the bits in?
I kept the size bits as an internal detail, I can define them in
tree-object-size.h and hae builtins.c (and others) use them.
>> +static void
>> +early_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call)
>> +{
>> + tree ost = gimple_call_arg (call, 1);
>> + tree lhs = gimple_call_lhs (call);
>> + gcc_assert (lhs != NULL_TREE);
>> +
>> + if (tree_fits_uhwi_p (ost))
>> + {
>> + unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
>> + tree ptr = gimple_call_arg (call, 0);
>> + if ((object_size_type == 1 || object_size_type == 3)
>> + && (TREE_CODE (ptr) == ADDR_EXPR || TREE_CODE (ptr) == SSA_NAME))
>
> I think it would be better to have early exits there to avoid
> indenting most of the function too much, because the function doesn't
> do anything otherwise. So:
> if (!tree_fits_uhwi_p (ost))
> return;
OK, I'll fix this.
>
> unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost);
> tree ptr = gimple_call_arg (call, 0);
> if (object_size_type != 1 && object_size_type != 3)
> return;
> if (TREE_CODE (ptr) != ADDR_EXPR && TREE_CODE (ptr) != SSA_NAME)
> return;
>
> tree type = ...
>
>> + {
>> + tree type = TREE_TYPE (lhs);
>> + tree bytes;
>> + if (compute_builtin_object_size (ptr, object_size_type, &bytes))
>> + {
>> + tree tem = make_ssa_name (type);
>> + gimple_call_set_lhs (call, tem);
>> + enum tree_code code
>> + = object_size_type & OST_MINIMUM ? MAX_EXPR : MIN_EXPR;
>> + tree cst = fold_convert (type, bytes);
>> + gimple *g = gimple_build_assign (lhs, code, tem, cst);
>> + gsi_insert_after (i, g, GSI_NEW_STMT);
>> + update_stmt (call);
>> + }
>> + }
>> + }
>
>> +/* Attempt to fold one __builtin_dynamic_object_size call in CALL into an
>> + expression and insert it at I. Return true if it succeeds. */
>> +
>> +static bool
>> +dynamic_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call)
>> +{
>> + unsigned numargs = gimple_call_num_args (call);
>> + tree *args = XALLOCAVEC (tree, numargs);
>> + args[0] = gimple_call_arg (call, 0);
>> + args[1] = gimple_call_arg (call, 1);
>
> Why it would have numargs different from 2? It is a builtin, and we reject
> ((__SIZE_TYPE__ (*) (const void *, int, int)) &__builtin_object_size) (x, 0, 3)
> etc. with error that the builtin must be directly called.
> And after all, you rely on it having at least 2 arguments anyway.
> So, just tree args[2]; instead of XALLOCAVEC and if you want,
> gcc_assert (numargs == 2);
> ?
Thanks, I'll fix this too.
Siddhesh
More information about the Gcc-patches
mailing list