Re: [V1][PATCH 2/3] Use the element_count atribute info in builtin object size [PR108896].

2023-05-30 Thread Qing Zhao via Gcc-patches


> On May 27, 2023, at 6:20 AM, Martin Uecker  wrote:
> 
> 
> Thank you for working on this!
> 
> 
> Here are a couple of comments:
> 
> How is the size for an object with FAM defined? 

Right now, with the attribute approach, the sizeof for the object with FAM is 
not impacted, and kept the same as before without this attribute. 

The information carried from the attribute only is used in _builtin_object_size 
and bound sanitizer. 

Doing this will help mitigating the existing source code to use this new 
information easier. 

If later this feature is promoted to C standard, I believe that the sizeof for 
the object with FAM should be updated too.  And the size information of the
FAM will be embedded into the TYPE. 

> 
> There are at least three possible choices:
> 
> offset(..) + N * sizeof
> sizeof(..) + N * sizeof
> or the size of a struct with the replacement array.
> 
> Or is this not relevant here?
> 
> 
> I would personally prefer an attribute which does
> not use a string,
Using “string” is the simplest implementation to prove the feasibility of this 
new attribute.
We can definitely use C expressions if we all think it’s necessary, the 
implementation in the C FE will be more complicate when using
C expression I think.  (When parsing the attribute, the type of the whole 
structure and other fields are not available yet, so, we might need to 
Delay the parsing of the attribute after the whole structure is done..)

> but uses C expressions, so that
> one could write something like this (although I would
> limit it initially to the most simple case) 
> 
> struct {
>  struct bar { int n; }* ptr;
>  int buf[] [[element_count(.ptr->n + 3)]];
> };
> 
> Of course, we could still support this later even
> if we use a string now.

Looks like that CLANG’s -fbounds-safely implements this attribute by using C 
expression as the argument and they added a late parse for C.
Not sure whether we should be compatible with CLANG on this, if so, we might 
need to do the same.

Thanks a lot for your suggestions and comments.

Qing
> 
> Martin
> 
> 
> 
> 
> Am Donnerstag, dem 25.05.2023 um 16:14 + schrieb Qing Zhao:
>> 2023-05-17 Qing Zhao 
>> 
>> gcc/ChangeLog:
>> 
>>  PR C/108896
>>  * tree-object-size.cc (addr_object_size): Use the element_count
>>  attribute info.
>>  * tree.cc (component_ref_has_element_count_p): New function.
>>  (component_ref_get_element_count): New function.
>>  * tree.h (component_ref_has_element_count_p): New prototype.
>>  (component_ref_get_element_count): New prototype.
>> 
>> gcc/testsuite/ChangeLog:
>> 
>>  PR C/108896
>>  * gcc.dg/flex-array-element-count-2.c: New test.
>> ---
>>  .../gcc.dg/flex-array-element-count-2.c   | 56 +++
>>  gcc/tree-object-size.cc   | 37 ++--
>>  gcc/tree.cc   | 93 +++
>>  gcc/tree.h| 10 ++
>>  4 files changed, 189 insertions(+), 7 deletions(-)
>>  create mode 100644 gcc/testsuite/gcc.dg/flex-array-element-count-2.c
>> 
>> diff --git a/gcc/testsuite/gcc.dg/flex-array-element-count-2.c 
>> b/gcc/testsuite/gcc.dg/flex-array-element-count-2.c
>> new file mode 100644
>> index 000..5a280e8c731
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/flex-array-element-count-2.c
>> @@ -0,0 +1,56 @@
>> +/* test the attribute element_count and its usage in
>> + * __builtin_dynamic_object_size.  */ 
>> +/* { dg-do run } */
>> +/* { dg-options "-O2" } */
>> +
>> +#include "builtin-object-size-common.h"
>> +
>> +#define expect(p, _v) do { \
>> +size_t v = _v; \
>> +if (p == v) \
>> +__builtin_printf ("ok:  %s == %zd\n", #p, p); \
>> +else \
>> +{  \
>> +  __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
>> +  FAIL (); \
>> +} \
>> +} while (0);
>> +
>> +struct flex {
>> +  int b;
>> +  int c[];
>> +} *array_flex;
>> +
>> +struct annotated {
>> +  int b;
>> +  int c[] __attribute__ ((element_count ("b")));
>> +} *array_annotated;
>> +
>> +void __attribute__((__noinline__)) setup (int normal_count, int attr_count)
>> +{
>> +  array_flex
>> += (struct flex *)malloc (sizeof (struct flex)
>> +   + normal_count *  sizeof (int));
>> +  array_flex->b = normal_count;
>> +
>> +  array_annotated
>> += (struct annotated *)malloc (sizeof (struct annotated)
>> ++ attr_count *  sizeof (int));
>> +  array_annotated->b = attr_count;
>> +
>> +  return;
>> +}
>> +
>> +void __attribute__((__noinline__)) test ()
>> +{
>> +expect(__builtin_dynamic_object_size(array_flex->c, 1), -1);
>> +expect(__builtin_dynamic_object_size(array_annotated->c, 1),
>> +   array_annotated->b * sizeof (int));
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +  setup (10,10);   
>> +  test ();
>> +  DONE ();
>> +}
>> diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
>> index 

Re: [V1][PATCH 2/3] Use the element_count atribute info in builtin object size [PR108896].

2023-05-27 Thread Martin Uecker via Gcc-patches


Thank you for working on this!


Here are a couple of comments:

How is the size for an object with FAM defined? 

There are at least three possible choices:

offset(..) + N * sizeof
sizeof(..) + N * sizeof
or the size of a struct with the replacement array.

Or is this not relevant here?


I would personally prefer an attribute which does
not use a string, but uses C expressions, so that
one could write something like this (although I would
limit it initially to the most simple case) 

struct {
  struct bar { int n; }* ptr;
  int buf[] [[element_count(.ptr->n + 3)]];
};

Of course, we could still support this later even
if we use a string now.

Martin




Am Donnerstag, dem 25.05.2023 um 16:14 + schrieb Qing Zhao:
> 2023-05-17 Qing Zhao 
> 
> gcc/ChangeLog:
> 
>   PR C/108896
>   * tree-object-size.cc (addr_object_size): Use the element_count
>   attribute info.
>   * tree.cc (component_ref_has_element_count_p): New function.
>   (component_ref_get_element_count): New function.
>   * tree.h (component_ref_has_element_count_p): New prototype.
>   (component_ref_get_element_count): New prototype.
> 
> gcc/testsuite/ChangeLog:
> 
>   PR C/108896
>   * gcc.dg/flex-array-element-count-2.c: New test.
> ---
>  .../gcc.dg/flex-array-element-count-2.c   | 56 +++
>  gcc/tree-object-size.cc   | 37 ++--
>  gcc/tree.cc   | 93 +++
>  gcc/tree.h| 10 ++
>  4 files changed, 189 insertions(+), 7 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/flex-array-element-count-2.c
> 
> diff --git a/gcc/testsuite/gcc.dg/flex-array-element-count-2.c 
> b/gcc/testsuite/gcc.dg/flex-array-element-count-2.c
> new file mode 100644
> index 000..5a280e8c731
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/flex-array-element-count-2.c
> @@ -0,0 +1,56 @@
> +/* test the attribute element_count and its usage in
> + * __builtin_dynamic_object_size.  */ 
> +/* { dg-do run } */
> +/* { dg-options "-O2" } */
> +
> +#include "builtin-object-size-common.h"
> +
> +#define expect(p, _v) do { \
> +size_t v = _v; \
> +if (p == v) \
> + __builtin_printf ("ok:  %s == %zd\n", #p, p); \
> +else \
> + {  \
> +   __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
> +   FAIL (); \
> + } \
> +} while (0);
> +
> +struct flex {
> +  int b;
> +  int c[];
> +} *array_flex;
> +
> +struct annotated {
> +  int b;
> +  int c[] __attribute__ ((element_count ("b")));
> +} *array_annotated;
> +
> +void __attribute__((__noinline__)) setup (int normal_count, int attr_count)
> +{
> +  array_flex
> += (struct flex *)malloc (sizeof (struct flex)
> ++ normal_count *  sizeof (int));
> +  array_flex->b = normal_count;
> +
> +  array_annotated
> += (struct annotated *)malloc (sizeof (struct annotated)
> + + attr_count *  sizeof (int));
> +  array_annotated->b = attr_count;
> +
> +  return;
> +}
> +
> +void __attribute__((__noinline__)) test ()
> +{
> +expect(__builtin_dynamic_object_size(array_flex->c, 1), -1);
> +expect(__builtin_dynamic_object_size(array_annotated->c, 1),
> +array_annotated->b * sizeof (int));
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +  setup (10,10);   
> +  test ();
> +  DONE ();
> +}
> diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
> index 9a936a91983..f9aadd59054 100644
> --- a/gcc/tree-object-size.cc
> +++ b/gcc/tree-object-size.cc
> @@ -585,6 +585,7 @@ addr_object_size (struct object_size_info *osi, 
> const_tree ptr,
>    if (pt_var != TREE_OPERAND (ptr, 0))
>  {
>    tree var;
> +  tree element_count_ref = NULL_TREE;
>  
> 
>    if (object_size_type & OST_SUBOBJECT)
>   {
> @@ -600,11 +601,12 @@ addr_object_size (struct object_size_info *osi, 
> const_tree ptr,
>   var = TREE_OPERAND (var, 0);
>     if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
>   var = TREE_OPERAND (var, 0);
> -   if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
> +   if (! component_ref_has_element_count_p (var)
> +  && ((! TYPE_SIZE_UNIT (TREE_TYPE (var))
>     || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
>     || (pt_var_size && TREE_CODE (pt_var_size) == INTEGER_CST
>     && tree_int_cst_lt (pt_var_size,
> -   TYPE_SIZE_UNIT (TREE_TYPE (var)
> +   TYPE_SIZE_UNIT (TREE_TYPE (var)))
>   var = pt_var;
>     else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF)
>   {
> @@ -612,6 +614,7 @@ addr_object_size (struct object_size_info *osi, 
> const_tree ptr,
>     /* For >fld, compute object size if fld isn't a flexible array
>    member.  */
>     bool is_flexible_array_mem_ref = false;
> +
>     while (v && v != pt_var)
>     

[V1][PATCH 2/3] Use the element_count atribute info in builtin object size [PR108896].

2023-05-25 Thread Qing Zhao via Gcc-patches
2023-05-17 Qing Zhao 

gcc/ChangeLog:

PR C/108896
* tree-object-size.cc (addr_object_size): Use the element_count
attribute info.
* tree.cc (component_ref_has_element_count_p): New function.
(component_ref_get_element_count): New function.
* tree.h (component_ref_has_element_count_p): New prototype.
(component_ref_get_element_count): New prototype.

gcc/testsuite/ChangeLog:

PR C/108896
* gcc.dg/flex-array-element-count-2.c: New test.
---
 .../gcc.dg/flex-array-element-count-2.c   | 56 +++
 gcc/tree-object-size.cc   | 37 ++--
 gcc/tree.cc   | 93 +++
 gcc/tree.h| 10 ++
 4 files changed, 189 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/flex-array-element-count-2.c

diff --git a/gcc/testsuite/gcc.dg/flex-array-element-count-2.c 
b/gcc/testsuite/gcc.dg/flex-array-element-count-2.c
new file mode 100644
index 000..5a280e8c731
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/flex-array-element-count-2.c
@@ -0,0 +1,56 @@
+/* test the attribute element_count and its usage in
+ * __builtin_dynamic_object_size.  */ 
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "builtin-object-size-common.h"
+
+#define expect(p, _v) do { \
+size_t v = _v; \
+if (p == v) \
+   __builtin_printf ("ok:  %s == %zd\n", #p, p); \
+else \
+   {  \
+ __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
+ FAIL (); \
+   } \
+} while (0);
+
+struct flex {
+  int b;
+  int c[];
+} *array_flex;
+
+struct annotated {
+  int b;
+  int c[] __attribute__ ((element_count ("b")));
+} *array_annotated;
+
+void __attribute__((__noinline__)) setup (int normal_count, int attr_count)
+{
+  array_flex
+= (struct flex *)malloc (sizeof (struct flex)
+  + normal_count *  sizeof (int));
+  array_flex->b = normal_count;
+
+  array_annotated
+= (struct annotated *)malloc (sizeof (struct annotated)
+   + attr_count *  sizeof (int));
+  array_annotated->b = attr_count;
+
+  return;
+}
+
+void __attribute__((__noinline__)) test ()
+{
+expect(__builtin_dynamic_object_size(array_flex->c, 1), -1);
+expect(__builtin_dynamic_object_size(array_annotated->c, 1),
+  array_annotated->b * sizeof (int));
+}
+
+int main(int argc, char *argv[])
+{
+  setup (10,10);   
+  test ();
+  DONE ();
+}
diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
index 9a936a91983..f9aadd59054 100644
--- a/gcc/tree-object-size.cc
+++ b/gcc/tree-object-size.cc
@@ -585,6 +585,7 @@ addr_object_size (struct object_size_info *osi, const_tree 
ptr,
   if (pt_var != TREE_OPERAND (ptr, 0))
 {
   tree var;
+  tree element_count_ref = NULL_TREE;
 
   if (object_size_type & OST_SUBOBJECT)
{
@@ -600,11 +601,12 @@ addr_object_size (struct object_size_info *osi, 
const_tree ptr,
var = TREE_OPERAND (var, 0);
  if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
var = TREE_OPERAND (var, 0);
- if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
+ if (! component_ref_has_element_count_p (var)
+&& ((! TYPE_SIZE_UNIT (TREE_TYPE (var))
  || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
  || (pt_var_size && TREE_CODE (pt_var_size) == INTEGER_CST
  && tree_int_cst_lt (pt_var_size,
- TYPE_SIZE_UNIT (TREE_TYPE (var)
+ TYPE_SIZE_UNIT (TREE_TYPE (var)))
var = pt_var;
  else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF)
{
@@ -612,6 +614,7 @@ addr_object_size (struct object_size_info *osi, const_tree 
ptr,
  /* For >fld, compute object size if fld isn't a flexible array
 member.  */
  bool is_flexible_array_mem_ref = false;
+
  while (v && v != pt_var)
switch (TREE_CODE (v))
  {
@@ -639,6 +642,8 @@ addr_object_size (struct object_size_info *osi, const_tree 
ptr,
break;
  }
is_flexible_array_mem_ref = array_ref_flexible_size_p (v);
+   element_count_ref = component_ref_get_element_count (v);
+
while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
  if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
  != UNION_TYPE
@@ -652,8 +657,11 @@ addr_object_size (struct object_size_info *osi, const_tree 
ptr,
   == RECORD_TYPE)
  {
/* compute object size only if v is not a
-  flexible array member.  */
-   if (!is_flexible_array_mem_ref)
+  flexible array