> On Jan 15, 2024, at 4:31 AM, Richard Biener <richard.guent...@gmail.com> 
> wrote:
> 
>> All my questions for unshare_expr relate to a  LTO bug that I currently 
>> stuck with
>> when using .ACCESS_WITH_SIZE in bound sanitizer (only with -flto, without 
>> -flto, no issue):
>> 
>> [opc@qinzhao-aarch64-ol8 gcc]$ sh t
>> during IPA pass: modref
>> t.c:20:1: internal compiler error: tree code ‘ssa_name’ is not supported in 
>> LTO streams
>> 0x14c3993 lto_write_tree
>>        ../../latest-gcc-write/gcc/lto-streamer-out.cc:561
>> 0x14c3aeb lto_output_tree_1
>> 
>> And the value of the tree node that triggered the ICE is:
>> (gdb) call debug_tree(expr)
>> <ssa_name 0xfffff5761e60 type <error_mark 0xfffff56c0e58>
>>    nothrow
>>    def_stmt
>>    version:13 in-free-list>
>> 
>> Is there any good way to debug LTO bug?
> 
> This happens usually when you have a VLA type and its type fields are not
> properly gimplified which usually happens because the frontend fails to
> insert a gimplification point for it (a DECL_EXPR).

I found an old gcc bug 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97172
ICE: tree code ‘ssa_name’ is not supported in LTO streams since 
r11-3303-g6450f07388f9fe57

Which is very similar to the bug I am having right now. 

After further study, I suspect that the issue I am having right now with the 
LTO streaming also 
relate to “unshare_expr”, “save_expr”, and the combination of these two, I 
suspect that
the current gcc cannot handle the combination of these two correctly for my 
case. 

My testing case is:

#include <stdlib.h>
void __attribute__((__noinline__)) setup_and_test_vla (int n1, int n2, int m)
{
   struct foo {
       int n;
       int p[][n2][n1] __attribute__((counted_by(n)));
   } *f;

   f = (struct foo *) malloc (sizeof(struct foo) + m*sizeof(int[n2][n1]));
   f->n = m;
   f->p[m][n2][n1]=1;
   return;
}

int main(int argc, char *argv[])
{
  setup_and_test_vla (10, 11, 20);
  return 0;
}

Failed with 
my_gcc -Os -fsanitize=bounds -flto

If changing either n1 or n2 to a constant, the testing passed. 
If deleting -flto, the testing passed too. 

I double checked my code per the suggestions provided by you and Jakub in this
email thread, and I think the code should be fine.

The code is following:

=====
504 /* Instrument array bounds for INDIRECT_REFs whose pointers are
505    POINTER_PLUS_EXPRs of calls to .ACCESS_WITH_SIZE. We create special
506    builtins that gets expanded in the sanopt pass, and make an array
507    dimension of it.  ARRAY is the pointer to the base of the array,
508    which is a call to .ACCESS_WITH_SIZE, *OFFSET is the offset to the
509    beginning of array.
510    Return NULL_TREE if no instrumentation is emitted.  */
511  
512 tree
513 ubsan_instrument_bounds_indirect_ref (location_t loc, tree array, tree 
*offset)
514 {
515   if (!is_access_with_size_p (array))
516     return NULL_TREE;
517   tree bound = get_bound_from_access_with_size (array);
518   /* The type of the call to .ACCESS_WITH_SIZE is a pointer type to
519      the element of the array.  */
520   tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
521   gcc_assert (bound);
522 
523   /* Given the offset, and the size of each element, the index can be
524      computed as: offset/element_size.  */
525   *offset = save_expr (*offset);
526   tree index = fold_build2 (EXACT_DIV_EXPR,
527                            sizetype, *offset,
528                            unshare_expr (element_size));
529   /* Create a "(T *) 0" tree node to describe the original array type.
530      We get the original array type from the first argument of the call to
531      .ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, num_bytes, -1).
532  
533      Originally, REF is a COMPONENT_REF with the original array type,
534      it was converted to a pointer to an ADDR_EXPR, and the ADDR_EXPR's
535      first operand is the original COMPONENT_REF.  */
536   tree ref = CALL_EXPR_ARG (array, 0);
537   tree array_type
538     = unshare_expr (TREE_TYPE (TREE_OPERAND (TREE_OPERAND(ref, 0), 0)));
539   tree zero_with_type = build_int_cst (build_pointer_type (array_type), 0);
540   return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS,
541                                        void_type_node, 3, zero_with_type,
542                                        index, bound);
543 }

=====

Inside gdb, the guilty IR failed in LTO streaming is from the above line 520:
TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array))),

When I use this tree node as an operand of the expression at line 526, I added 
unshare_expr. 

However, I still see the guilty IR as in gdb:

            unit-size <mult_expr 0xfffff5aabf90 type <integer_type 
0xfffff57c0000 sizetype>
                side-effects
                arg:0 <mult_expr 0xfffff5aabf68 type <integer_type 
0xfffff57c0000 sizetype>

                    arg:0 <ssa_name 0xfffff5761e18 type <error_mark 
0xfffff56c0e58>
                        nothrow
                        def_stmt
                        version:12 in-free-list>
                    arg:1 <ssa_name 0xfffff5761e60 type <error_mark 
0xfffff56c0e58>
                        nothrow
                        def_stmt
                        version:13 in-free-list>>
                arg:1 <integer_cst 0xfffff56c10c8 constant 4>>


I have been stuck with this bug for quite some time. 
Any help is helpful.

Qing

> 
>> Thanks a lot for the help.
>> 
>> Qing
>> 

Reply via email to