When we're passing ADDR_EXPR of long long int argument in -m32 mode, the ADDR_EXPR's VAR_DECL has to have its DECL_RTL set and corresponding stack slot allocated, it seems. Otherwise we ICE when expanding a function with such argument. This patch does that and adds a testcase for it.
Bootstrapped, ran ubsan testsuite on x86_64-unknown-linux-gnu. Ok for trunk? 2013-12-05 Marek Polacek <pola...@redhat.com> PR sanitizer/59333 * ubsan.c: Include rtl.h. (ubsan_encode_value): Add new parameter. If expanding, assign a stack slot for DECL_RTL of the temporary. Handle BOOLEAN_TYPE and ENUMERAL_TYPE. (ubsan_build_overflow_builtin): Adjust ubsan_encode_value call. * ubsan.h (ubsan_encode_value): Adjust declaration. c-family/ * c-ubsan.c (ubsan_instrument_division): Adjust ubsan_encode_value call. (ubsan_instrument_shift): Likewise. (ubsan_instrument_vla): Likewise. testsuite/ * c-c++-common/ubsan/pr59333.c: New test. --- gcc/c-family/c-ubsan.c.mp 2013-12-05 11:24:08.570201260 +0100 +++ gcc/c-family/c-ubsan.c 2013-12-05 11:26:25.401721067 +0100 @@ -78,8 +78,8 @@ ubsan_instrument_division (location_t lo NULL_TREE); data = build_fold_addr_expr_loc (loc, data); tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW); - tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0), - ubsan_encode_value (op1)); + tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0, false), + ubsan_encode_value (op1, false)); t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node); return t; @@ -152,8 +152,8 @@ ubsan_instrument_shift (location_t loc, t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt ? tt : integer_zero_node); tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS); - tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0), - ubsan_encode_value (op1)); + tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0, false), + ubsan_encode_value (op1, false)); t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node); return t; @@ -174,7 +174,8 @@ ubsan_instrument_vla (location_t loc, tr NULL_TREE); data = build_fold_addr_expr_loc (loc, data); tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE); - tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size)); + tt = build_call_expr_loc (loc, tt, 2, data, + ubsan_encode_value (size, false)); t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node); return t; --- gcc/ubsan.h.mp 2013-12-05 11:25:18.979469651 +0100 +++ gcc/ubsan.h 2013-12-05 11:25:28.958507098 +0100 @@ -41,7 +41,7 @@ extern tree ubsan_instrument_unreachable extern tree ubsan_create_data (const char *, location_t, const struct ubsan_mismatch_data *, ...); extern tree ubsan_type_descriptor (tree, bool); -extern tree ubsan_encode_value (tree); +extern tree ubsan_encode_value (tree, bool); extern bool is_ubsan_builtin_p (tree); extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, tree); --- gcc/ubsan.c.mp 2013-12-05 09:40:39.676771966 +0100 +++ gcc/ubsan.c 2013-12-05 11:35:06.907851149 +0100 @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. #include "cfgloop.h" #include "ubsan.h" #include "c-family/c-common.h" +#include "rtl.h" /* Map from a tree to a VAR_DECL tree. */ @@ -102,45 +103,50 @@ decl_for_type_insert (tree type, tree de /* Helper routine, which encodes a value in the pointer_sized_int_node. Arguments with precision <= POINTER_SIZE are passed directly, - the rest is passed by reference. T is a value we are to encode. */ + the rest is passed by reference. T is a value we are to encode. + IN_EXPAND_P is true if this function is called during expansion. */ tree -ubsan_encode_value (tree t) +ubsan_encode_value (tree t, bool in_expand_p) { tree type = TREE_TYPE (t); - switch (TREE_CODE (type)) - { - case INTEGER_TYPE: - if (TYPE_PRECISION (type) <= POINTER_SIZE) + const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type)); + if (bitsize <= POINTER_SIZE) + switch (TREE_CODE (type)) + { + case BOOLEAN_TYPE: + case ENUMERAL_TYPE: + case INTEGER_TYPE: return fold_build1 (NOP_EXPR, pointer_sized_int_node, t); + case REAL_TYPE: + { + tree itype = build_nonstandard_integer_type (bitsize, true); + t = fold_build1 (VIEW_CONVERT_EXPR, itype, t); + return fold_convert (pointer_sized_int_node, t); + } + default: + gcc_unreachable (); + } + else + { + if (!TREE_ADDRESSABLE (t)) + { + /* The reason for this is that we don't want to pessimize + code by making vars unnecessarily addressable. */ + tree var = create_tmp_var (type, NULL); + tree tem = build2 (MODIFY_EXPR, void_type_node, var, t); + if (in_expand_p) + { + SET_DECL_RTL (var, + assign_stack_temp_for_type (TYPE_MODE (type), + GET_MODE_SIZE (TYPE_MODE (type)), type)); + return build_fold_addr_expr (var); + } + t = build_fold_addr_expr (var); + return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t); + } else return build_fold_addr_expr (t); - case REAL_TYPE: - { - unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type)); - if (bitsize <= POINTER_SIZE) - { - tree itype = build_nonstandard_integer_type (bitsize, true); - t = fold_build1 (VIEW_CONVERT_EXPR, itype, t); - return fold_convert (pointer_sized_int_node, t); - } - else - { - if (!TREE_ADDRESSABLE (t)) - { - /* The reason for this is that we don't want to pessimize - code by making vars unnecessarily addressable. */ - tree var = create_tmp_var (TREE_TYPE (t), NULL); - tree tem = build2 (MODIFY_EXPR, void_type_node, var, t); - t = build_fold_addr_expr (var); - return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t); - } - else - return build_fold_addr_expr (t); - } - } - default: - gcc_unreachable (); } } @@ -663,8 +669,9 @@ ubsan_build_overflow_builtin (tree_code tree fn = builtin_decl_explicit (fn_code); return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR), build_fold_addr_expr_loc (loc, data), - ubsan_encode_value (op0), - op1 ? ubsan_encode_value (op1) : NULL_TREE); + ubsan_encode_value (op0, true), + op1 ? ubsan_encode_value (op1, true) + : NULL_TREE); } /* Perform the signed integer instrumentation. GSI is the iterator --- gcc/testsuite/c-c++-common/ubsan/pr59333.c.mp 2013-12-05 11:30:36.984759390 +0100 +++ gcc/testsuite/c-c++-common/ubsan/pr59333.c 2013-12-05 11:31:36.599979040 +0100 @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=undefined" } */ + +long long int +foo (long long int i, long long int j) +{ + return i * j; +} Marek