> On Apr 28, 2025, at 09:40, Richard Biener <[email protected]> wrote:
>
> On Mon, Apr 28, 2025 at 2:56 PM Qing Zhao <[email protected]> wrote:
>>
>>
>>
>>> On Apr 28, 2025, at 06:49, Richard Biener <[email protected]>
>>> wrote:
>>>
>>> On Wed, Apr 23, 2025 at 6:09 PM Qing Zhao <[email protected]> wrote:
>>>>
>>>> Richard,
>>>>
>>>> Thanks a lot for the hint.
>>>>
>>>>> On Apr 23, 2025, at 04:17, Richard Biener <[email protected]>
>>>>> wrote:
>>>>>
>>>>>> I have met the following issue when I tried to implement the following
>>>>>> into tree-object-size.cc:
>>>>>> (And this took me quite some time, still don’t know what’s the best
>>>>>> solution)
>>>>>>
>>>>>>> On Apr 16, 2025, at 10:46, Qing Zhao <[email protected]> wrote:
>>>>>>>
>>>>>>> 3. When generating the reference to the field member in
>>>>>>> tree-object-size, we should guard this reference with a checking
>>>>>>> on the pointer to the structure is valid. i.e:
>>>>>>>
>>>>>>> struct annotated {
>>>>>>> size_t count;
>>>>>>> char array[] __attribute__((counted_by (count)));
>>>>>>> };
>>>>>>>
>>>>>>> static size_t __attribute__((__noinline__)) size_of (struct annotated *
>>>>>>> obj)
>>>>>>> {
>>>>>>> return __builtin_dynamic_object_size (obj, 1);
>>>>>>> }
>>>>>>>
>>>>>>> When we try to generate the reference to obj->count when evaluating
>>>>>>> __builtin_dynamic_object_size (obj, 1),
>>>>>>> We should generate the following:
>>>>>>>
>>>>>>> If (obj != NULL)
>>>>>>> * (&obj->count)
>>>>>>>
>>>>>>> To make sure that the pointer to the structure object is valid first.
>>>>>>>
>>>>>>
>>>>>> Then as I generate the following size_expr in tree-object-size.cc:
>>>>>>
>>>>>> Breakpoint 1, gimplify_size_expressions (osi=0xffffffffdf30)
>>>>>> at ../../latest-gcc-write/gcc/tree-object-size.cc:1178
>>>>>> 1178 force_gimple_operand (size_expr, &seq, true, NULL);
>>>>>> (gdb) call debug_generic_expr(size_expr)
>>>>>> _4 = obj_2(D) != 0B ? (sizetype) (int) MAX_EXPR <(sizetype) MAX_EXPR
>>>>>> <MEM <int> [(void *)&*obj_2(D)], 0> + 4, 4> : 18446744073709551615
>>>>>>
>>>>>> When calling “force_gimple_operand” for the above size_expr, I got the
>>>>>> following ICE in gimplify_modify_expr, at gimplify.cc:7505:
>>>>>
>>>>> You shouldn't really force_gimple_operand to a MODIFY_EXPR but instead
>>>>> only to its RHS.
>>>>
>>>> Do you mean: instead of
>>>>
>>>> force_gimple_operand (size_expr, &seq, true, NULL);
>>>>
>>>> I should
>>>>
>>>> 1178 if (TREE_CODE (size_expr) == MODIFY_EXPR)
>>>> 1179 {
>>>> 1180 tree rhs = TREE_OPERAND (size_expr, 1);
>>>> 1181 force_gimple_operand (rhs, &seq, true, NULL);
>>>> 1182 }
>>>>
>>>> ?
>>>>
>>>> However, with this change, I got the exactly same error at the above line
>>>> 1181.
>>>> (gdb) call debug_generic_expr(rhs)
>>>> obj_2(D) != 0B ? (sizetype) (int) MAX_EXPR <(sizetype) MAX_EXPR <MEM <int>
>>>> [(void *)&*obj_2(D)], 0> + 4, 4> : 18446744073709551615
>>>>
>>>> The issue is still the same as before.
>>>> So, I am wondering whether the above size expression I generated has some
>>>> issue?
>>>> Or the routine “force_gimple_operand” has some bug when the tree expr is
>>>> a COND_EXPR expression?
>>>
>>> Well, one issue is that the true case can trap while the false case
>>> does not, and force_gimple_operand
>>> cannot create a CFG to preserve the conditional execution. If that's
>>> not an issue you need to
>>> create the COND_EXPR in gimple form from the start and not try to do
>>> easy by going though
>>> gimpification.
>>
>> Okay, so, I need to create the following:
>>
>> If (obj != NULL)
>> size = (sizetype) (int) MAX_EXPR <(sizetype) MAX_EXPR <MEM <int> [(void
>> *)&*obj_2(D)], 0> + 4, 4>
>> else
>> size = -1;
>>
>> Directly in gimple form and insert it to the control flow of the routine.
>
> I guess so.
>
>> Is there a similar example in gcc source code I can take a look at?
>
> I think the sanitizers insert control flow, the profiling code definitely
> does.
Okay, will take a look and see how to do it.
Thanks a lot for your help.
>
>> Thanks a lot.
>>
>> Qing
>>
>>> Richard.
>>>
>>>>
>>>> Thanks.
>>>>
>>>> Qing
>>>>
>>>> The size_expr is a COND_EXPR:
>>>>
>>>> (gdb) call debug_tree(rhs)
>>>> <cond_expr 0x7fffea281e10
>>>> type <integer_type 0x7fffea282000 sizetype public unsigned DI
>>>> size <integer_cst 0x7fffea262f60 constant 64>
>>>> unit-size <integer_cst 0x7fffea262f78 constant 8>
>>>> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
>>>> 0x7fffea282000 precision:64 min <integer_cst 0x7fffea262f90 0> max
>>>> <integer_cst 0x7fffea263640 18446744073709551615>>
>>>>
>>>> arg:0 <ne_expr 0x7fffea0cd0f0
>>>> type <boolean_type 0x7fffea282b28 _Bool public unsigned QI
>>>> size <integer_cst 0x7fffea284060 constant 8>
>>>> unit-size <integer_cst 0x7fffea284078 constant 1>
>>>> align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
>>>> 0x7fffea282b28 precision:1 min <integer_cst 0x7fffea2842b8 0> max
>>>> <integer_cst 0x7fffea2842e8 1>>
>>>> arg:0 <ssa_name 0x7fffea26d9d8 type <pointer_type
>>>> 0x7fffea0bc7e0>
>>>> visited var <parm_decl 0x7fffea0bb440 obj>
>>>> def_stmt GIMPLE_NOP
>>>> version:2
>>>> ptr-info 0x7fffea091918>
>>>> arg:1 <integer_cst 0x7fffea091780 constant 0>>
>>>> arg:1 <nop_expr 0x7fffea0c2680 type <integer_type 0x7fffea282000
>>>> sizetype>
>>>> arg:0 <nop_expr 0x7fffea0c2660 type <integer_type
>>>> 0x7fffea2825e8 int>
>>>> arg:0 <max_expr 0x7fffea0cd0a0 type <integer_type
>>>> 0x7fffea282000 sizetype>
>>>> arg:0 <plus_expr 0x7fffea0cd078 type
>>>> <integer_type 0x7fffea282000 sizetype>
>>>> arg:0 <nop_expr 0x7fffea0c2640 type
>>>> <integer_type 0x7fffea282000 sizetype>
>>>> arg:0 <max_expr
>>>> 0x7fffea0cd050 type <integer_type 0x7fffea2825e8 int>
>>>> arg:0 <mem_ref 0x7fffea0cd000> arg:1
>>>> <integer_cst 0x7fffea284300 0>>>
>>>> arg:1 <integer_cst 0x7fffea2841c8 constant 4>> arg:1
>>>> <integer_cst 0x7fffea2841c8 4>>>>
>>>> arg:2 <integer_cst 0x7fffea263640 type <integer_type 0x7fffea282000
>>>> sizetype> constant 18446744073709551615>>
>>>>
>>>>>
>>>>>> (gdb) c
>>>>>> Continuing.
>>>>>> during GIMPLE pass: objsz
>>>>>> dump file: a-t.c.110t.objsz1
>>>>>> In function ‘size_of’:
>>>>>> cc1: internal compiler error: in gimplify_modify_expr, at
>>>>>> gimplify.cc:7505
>>>>>> 0x36feb67 internal_error(char const*, ...)
>>>>>> ../../latest-gcc-write/gcc/diagnostic-global-context.cc:517
>>>>>> 0x36ccd67 fancy_abort(char const*, int, char const*)
>>>>>> ../../latest-gcc-write/gcc/diagnostic.cc:1749
>>>>>> 0x14fa8ab gimplify_modify_expr
>>>>>> ../../latest-gcc-write/gcc/gimplify.cc:7505
>>>>>> 0x15354c3 gimplify_expr(tree_node**, gimple**, gimple**, bool
>>>>>> (*)(tree_node*), int)
>>>>>> ../../latest-gcc-write/gcc/gimplify.cc:19530
>>>>>> 0x14fe1b3 gimplify_stmt(tree_node**, gimple**)
>>>>>> ../../latest-gcc-write/gcc/gimplify.cc:8458
>>>>>> ….
>>>>>> 0x1b07757 gimplify_size_expressions
>>>>>> ../../latest-gcc-write/gcc/tree-object-size.cc:1178
>>>>>>
>>>>>> I debugged into this a little bit, and found that the following are the
>>>>>> reason for the assertion failure in the routine “gimplify_modify_expr”
>>>>>> of gimplify.cc:
>>>>>>
>>>>>> 1. The assertion failure is:
>>>>>>
>>>>>> 7502 if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
>>>>>> 7503 {
>>>>>> 7504 /* We should have got an SSA name from the start. */
>>>>>> 7505 gcc_assert (TREE_CODE (*to_p) == SSA_NAME
>>>>>> 7506 || ! gimple_in_ssa_p (cfun));
>>>>>> 7507 }
>>>>>>
>>>>>> 2. The above assertion failure is issued for the following temporary
>>>>>> tree:
>>>>>>
>>>>>> (gdb) call debug_generic_expr(*to_p)
>>>>>> iftmp.2
>>>>>> (gdb) call debug_generic_expr(*expr_p)
>>>>>> iftmp.2 = (sizetype) _10
>>>>>>
>>>>>> In the above, the temporary variable “iftmp.2” triggered the assertion
>>>>>> since it’s NOT a SSA_NAME but the gimple_in_ssa_p (cfun) is TRUE.
>>>>>>
>>>>>> 3. As I checked, this temporary variable “iftmp.2” was generated at line
>>>>>> 5498 in the routine “gimplify_cond_expr” of gimplify.cc:
>>>>>>
>>>>>> 5477 /* If this COND_EXPR has a value, copy the values into a
>>>>>> temporary within
>>>>>> 5478 the arms. */
>>>>>> 5479 if (!VOID_TYPE_P (type))
>>>>>> 5480 {
>>>>>> …..
>>>>>> 5498 tmp = create_tmp_var (type, "iftmp”);
>>>>>> ...
>>>>>> 5537 }
>>>>>>
>>>>>> 4. And then later, this temporary created here “iftmp.2” triggered the
>>>>>> assertion failure.
>>>>>>
>>>>>> Right now, I have the following questions:
>>>>>>
>>>>>> 1. Can I generate a size_expr as complicate as the following in
>>>>>> tree-object-size.cc:
>>>>>>
>>>>>> _4 = obj_2(D) != 0B ? (sizetype) (int) MAX_EXPR <(sizetype) MAX_EXPR
>>>>>> <MEM <int> [(void *)&*obj_2(D)], 0> + 4, 4> : 18446744073709551615
>>>>>>
>>>>>> 2. If Yes to 1, is this a bug in “gimplify_cond_expr”? Shall we call
>>>>>> “make_ssa_name” after the call to “create_tmp_var” if
>>>>>> “gimple_in_ssa_p(cfun)” is TRUE?
>>>>>>
>>>>>> 3. If No to 1, how can we check whether the pointer is zero before
>>>>>> dereference from it to access its field?
>>>>>>
>>>>>> Thanks a lot for any hints.
>>>>>>
>>>>>> Qing