> On Apr 28, 2025, at 09:40, Richard Biener <richard.guent...@gmail.com> wrote: > > On Mon, Apr 28, 2025 at 2:56 PM Qing Zhao <qing.z...@oracle.com> wrote: >> >> >> >>> On Apr 28, 2025, at 06:49, Richard Biener <richard.guent...@gmail.com> >>> wrote: >>> >>> On Wed, Apr 23, 2025 at 6:09 PM Qing Zhao <qing.z...@oracle.com> wrote: >>>> >>>> Richard, >>>> >>>> Thanks a lot for the hint. >>>> >>>>> On Apr 23, 2025, at 04:17, Richard Biener <richard.guent...@gmail.com> >>>>> 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 <qing.z...@oracle.com> 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