> 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 >>