public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Matthew Malcomson <matmal01@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/ARM/heads/morello)] morello: Add mechanism to prevent over-accessing a bitfield in memory Date: Mon, 28 Feb 2022 12:08:04 +0000 (GMT) [thread overview] Message-ID: <20220228120804.D13473858430@sourceware.org> (raw) https://gcc.gnu.org/g:120ae017c0f5b24125337dcca67fa885c10a97e3 commit 120ae017c0f5b24125337dcca67fa885c10a97e3 Author: Stam Markianos-Wright <stam.markianos-wright@arm.com> Date: Fri Dec 10 16:33:29 2021 +0000 morello: Add mechanism to prevent over-accessing a bitfield in memory This patch adds a new mechanism to prevent over-reading when accessing a bitfield in memory. This would previously cause a Capability Bounds Fault exception to be raised at execution time. So GCC's internals did already have a mechanism to prevent over-writing/over-storing bitfields using the bitregion_end and bitregion_start parameters in the store_*_bitfield_* functions. For loading from memory this mechanism doesn't exit. The extract_*_bitfield_* functions all don't even have the bitregion_end, bitregion_start parameters and GCC would always assume that over-reading is fine. To resolve this I have extended the extract_* functions so that they do take the bitregion_end, bitregion_start parameters and can use the same low-level logic (in get_best_mode and next_mode) to limit the mode of the memory access to prevent over-reading. Similarly, further logic is transferred over to become aware of these limits. Diff: --- gcc/calls.c | 6 +-- gcc/expmed.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++---------- gcc/expmed.h | 3 +- gcc/expr.c | 61 ++++++++++++++++++++++------- gcc/function.c | 2 +- 5 files changed, 154 insertions(+), 39 deletions(-) diff --git a/gcc/calls.c b/gcc/calls.c index 36c52447f77..6c38afee29b 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1192,7 +1192,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals) int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD); args[i].aligned_regs[j] = reg; - word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX, + word = extract_bit_field (word, bitsize, 0, 1, 0, 0, NULL_RTX, word_mode, word_mode, false, NULL); /* There is no need to restrict this code to loading items @@ -3130,8 +3130,8 @@ load_register_parameters (struct arg_data *args, int num_actuals, rtx dest = gen_rtx_REG (word_mode, REGNO (reg) + nregs - 1); unsigned int bitoff = (nregs - 1) * BITS_PER_WORD; unsigned int bitsize = const_size * BITS_PER_UNIT - bitoff; - rtx x = extract_bit_field (mem, bitsize, bitoff, 1, dest, - word_mode, word_mode, false, + rtx x = extract_bit_field (mem, bitsize, bitoff, 1, 0, 0, + dest, word_mode, word_mode, false, NULL); if (BYTES_BIG_ENDIAN) x = expand_shift (LSHIFT_EXPR, word_mode, x, diff --git a/gcc/expmed.c b/gcc/expmed.c index 04d0e14028d..e6cb4cb5600 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -71,18 +71,21 @@ static void store_split_bit_field (rtx, opt_scalar_int_mode, rtx, scalar_int_mode, bool); static rtx extract_integral_bit_field (rtx, opt_scalar_int_mode, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, int, rtx, + unsigned HOST_WIDE_INT, + poly_uint64, poly_uint64, int, rtx, machine_mode, machine_mode, bool, bool); static rtx extract_fixed_bit_field (machine_mode, rtx, opt_scalar_int_mode, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, rtx, int, bool); + unsigned HOST_WIDE_INT, poly_uint64, + poly_uint64, rtx, int, bool); static rtx extract_fixed_bit_field_1 (machine_mode, rtx, scalar_int_mode, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, rtx, int, bool); static rtx lshift_value (machine_mode, unsigned HOST_WIDE_INT, int); static rtx extract_split_bit_field (rtx, opt_scalar_int_mode, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, int, bool); + unsigned HOST_WIDE_INT, poly_uint64, + poly_uint64, int, bool); static void do_cmp_and_jump (rtx, rtx, enum rtx_code, machine_mode, rtx_code_label *); static rtx expand_smod_pow2 (scalar_int_mode, rtx, HOST_WIDE_INT); static rtx expand_sdiv_pow2 (scalar_int_mode, rtx, HOST_WIDE_INT); @@ -975,8 +978,9 @@ store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, rtx value_word = fieldmode == BLKmode ? extract_bit_field (value, new_bitsize, wordnum * BITS_PER_WORD, - 1, NULL_RTX, word_mode, word_mode, false, - NULL) + 1, wordnum * BITS_PER_WORD, bitregion_end, + NULL_RTX, word_mode, word_mode, + false, NULL) : operand_subword_force (value, wordnum, value_mode); if (!store_bit_field_1 (op0, new_bitsize, @@ -1421,6 +1425,7 @@ store_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, part = extract_fixed_bit_field (word_mode, value, value_mode, thissize, bitsize - bitsdone - thissize, + bitregion_start, bitregion_end, NULL_RTX, 1, false); else /* The args are chosen so that the last part includes the @@ -1429,6 +1434,7 @@ store_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, part = extract_fixed_bit_field (word_mode, value, value_mode, thissize, total_bits - bitsize + bitsdone, + bitregion_start, bitregion_end, NULL_RTX, 1, false); } else @@ -1443,11 +1449,13 @@ store_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, part = extract_fixed_bit_field (word_mode, value, value_mode, thissize, total_bits - bitsdone - thissize, + bitregion_start, bitregion_end, NULL_RTX, 1, false); else part = extract_fixed_bit_field (word_mode, value, value_mode, - thissize, bitsdone, NULL_RTX, - 1, false); + thissize, bitsdone, + bitregion_start, bitregion_end, + NULL_RTX, 1, false); } /* If OP0 is a register, then handle OFFSET here. */ @@ -1616,6 +1624,7 @@ extract_bit_field_as_subreg (machine_mode mode, rtx op0, static rtx extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, + poly_uint64 bitregion_start, poly_uint64 bitregion_end, int unsignedp, rtx target, machine_mode mode, machine_mode tmode, bool reverse, bool fallback_p, rtx *alt_rtl) @@ -1845,7 +1854,8 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, /* From here on we need to be looking at a fixed-size insertion. */ return extract_integral_bit_field (op0, op0_mode, bitsize.to_constant (), - bitnum.to_constant (), unsignedp, + bitnum.to_constant (), bitregion_start, + bitregion_end, unsignedp, target, mode, tmode, reverse, fallback_p); } @@ -1857,7 +1867,9 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, static rtx extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitnum, int unsignedp, + unsigned HOST_WIDE_INT bitnum, + poly_uint64 bitregion_start, + poly_uint64 bitregion_end, int unsignedp, rtx target, machine_mode mode, machine_mode tmode, bool reverse, bool fallback_p) { @@ -1909,7 +1921,8 @@ extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, rtx result_part = extract_bit_field_1 (op0, MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD), - bitnum + bit_offset, 1, target_part, + bitnum + bit_offset, bitregion_start, + bitregion_end, 1, target_part, mode, word_mode, reverse, fallback_p, NULL); gcc_assert (target_part); @@ -1958,6 +1971,7 @@ extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, if (!fallback_p) return NULL_RTX; target = extract_split_bit_field (op0, op0_mode, bitsize, bitnum, + bitregion_start, bitregion_end, unsignedp, reverse); return convert_extracted_bit_field (target, mode, tmode, unsignedp); } @@ -2009,11 +2023,13 @@ extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, bitfield from that. */ unsigned HOST_WIDE_INT bitpos; rtx xop0 = adjust_bit_field_mem_for_reg (pattern, op0, bitsize, bitnum, - 0, 0, tmode, &bitpos); + bitregion_start, bitregion_end, + tmode, &bitpos); if (xop0) { xop0 = copy_to_reg (xop0); rtx result = extract_bit_field_1 (xop0, bitsize, bitpos, + bitregion_start, bitregion_end, unsignedp, target, mode, tmode, reverse, false, NULL); if (result) @@ -2034,7 +2050,8 @@ extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, int_mode = int_mode_for_mode (mode).require (); target = extract_fixed_bit_field (int_mode, op0, op0_mode, bitsize, - bitnum, target, unsignedp, reverse); + bitnum, bitregion_start, bitregion_end, + target, unsignedp, reverse); /* Complex values must be reversed piecewise, so we need to undo the global reversal, convert to the complex mode and reverse again. */ @@ -2073,7 +2090,8 @@ extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode, rtx extract_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, - int unsignedp, rtx target, machine_mode mode, + int unsignedp, poly_uint64 bitregion_start, + poly_uint64 bitregion_end, rtx target, machine_mode mode, machine_mode tmode, bool reverse, rtx *alt_rtl) { machine_mode mode1; @@ -2092,7 +2110,7 @@ extract_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, && bitnum.is_constant (&ibitnum) && is_a <scalar_int_mode> (mode1, &int_mode) && strict_volatile_bitfield_p (str_rtx, ibitsize, ibitnum, - int_mode, 0, 0)) + int_mode, bitregion_start, bitregion_end)) { /* Extraction of a full INT_MODE value can be done with a simple load. We know here that the field can be accessed with one single @@ -2112,11 +2130,38 @@ extract_bit_field (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, &ibitnum); gcc_assert (ibitnum + ibitsize <= GET_MODE_BITSIZE (int_mode)); str_rtx = copy_to_reg (str_rtx); - return extract_bit_field_1 (str_rtx, ibitsize, ibitnum, unsignedp, + return extract_bit_field_1 (str_rtx, ibitsize, ibitnum, bitregion_start, + bitregion_end, unsignedp, target, mode, tmode, reverse, true, alt_rtl); } - return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp, + /* If bitregion_start has been set to a value, then we are compiling for a + target that limits memory accesses to tight bounds so we must not touch + bits outside the bit region. Adjust the address to start at the beginning of the + bit region. */ + if (MEM_P (str_rtx) && maybe_ne (bitregion_start, 0U)) + { + scalar_int_mode best_mode; + machine_mode addr_mode = VOIDmode; + + poly_uint64 offset = exact_div (bitregion_start, BITS_PER_UNIT); + bitnum -= bitregion_start; + poly_int64 size = bits_to_bytes_round_up (bitnum + bitsize); + bitregion_end -= bitregion_start; + bitregion_start = 0; + if (bitsize.is_constant (&ibitsize) + && bitnum.is_constant (&ibitnum) + && get_best_mode (ibitsize, ibitnum, + bitregion_start, bitregion_end, + MEM_ALIGN (str_rtx), INT_MAX, + MEM_VOLATILE_P (str_rtx), &best_mode)) + addr_mode = best_mode; + str_rtx = adjust_bitfield_address_size (str_rtx, addr_mode, + offset, size); + } + + return extract_bit_field_1 (str_rtx, bitsize, bitnum, bitregion_start, + bitregion_end, unsignedp, target, mode, tmode, reverse, true, alt_rtl); } \f @@ -2135,17 +2180,27 @@ static rtx extract_fixed_bit_field (machine_mode tmode, rtx op0, opt_scalar_int_mode op0_mode, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitnum, rtx target, + unsigned HOST_WIDE_INT bitnum, + poly_uint64 bitregion_start, + poly_uint64 bitregion_end, rtx target, int unsignedp, bool reverse) { scalar_int_mode mode; if (MEM_P (op0)) { - if (!get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0), - BITS_PER_WORD, MEM_VOLATILE_P (op0), &mode)) + unsigned int max_bitsize = BITS_PER_WORD; + scalar_int_mode imode; + if (op0_mode.exists (&imode) && GET_MODE_BITSIZE (imode) < max_bitsize + && maybe_ne (bitregion_end, 0U)) + max_bitsize = GET_MODE_BITSIZE (imode); + + if (!get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end, + MEM_ALIGN (op0), max_bitsize, MEM_VOLATILE_P (op0), + &mode)) /* The only way this should occur is if the field spans word boundaries. */ return extract_split_bit_field (op0, op0_mode, bitsize, bitnum, + bitregion_start, bitregion_end, unsignedp, reverse); op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum); @@ -2263,7 +2318,10 @@ lshift_value (machine_mode mode, unsigned HOST_WIDE_INT value, static rtx extract_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitpos, int unsignedp, + unsigned HOST_WIDE_INT bitpos, + poly_uint64 bitregion_start, + poly_uint64 bitregion_end, + int unsignedp, bool reverse) { unsigned int unit; @@ -2278,6 +2336,13 @@ extract_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, else unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD); + /* For capability targets, if OP0 is a memory with a mode, + then UNIT must not be larger than OP0's mode as well. + Otherwise, extract_fixed_bit_field will call us + again, and we will mutually recurse forever. */ + if (MEM_P (op0) && op0_mode.exists () && maybe_ne (bitregion_end, 0U)) + unit = MIN (unit, GET_MODE_BITSIZE (op0_mode.require ())); + while (bitsdone < bitsize) { unsigned HOST_WIDE_INT thissize; @@ -2288,6 +2353,19 @@ extract_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, offset = (bitpos + bitsdone) / unit; thispos = (bitpos + bitsdone) % unit; + /* For capability targets the region of bytes we can read is restricted + by the capability bounds, so we must decrease UNIT close to the end + of the region as needed. */ + if (maybe_ne (bitregion_end, 0U) + && unit > BITS_PER_UNIT + && maybe_gt (bitpos + bitsdone - thispos + unit, bitregion_end + 1) + && !REG_P (op0) + && (GET_CODE (op0) != SUBREG || !REG_P (SUBREG_REG (op0)))) + { + unit = unit / 2; + continue; + } + /* THISSIZE must not overrun a word boundary. Otherwise, extract_fixed_bit_field will call us again, and we will mutually recurse forever. */ @@ -2309,7 +2387,8 @@ extract_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode, OFFSET is in UNITs, and UNIT is in bits. */ part = extract_fixed_bit_field (word_mode, op0_piece, op0_piece_mode, thissize, offset * unit + thispos, - 0, 1, reverse); + bitregion_start, bitregion_end, + NULL_RTX, 1, reverse); bitsdone += thissize; /* Shift this part into place for the result. */ diff --git a/gcc/expmed.h b/gcc/expmed.h index c10d1182c31..f3c5374a452 100644 --- a/gcc/expmed.h +++ b/gcc/expmed.h @@ -740,7 +740,8 @@ extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx, extern void store_bit_field (rtx, poly_uint64, poly_uint64, poly_uint64, poly_uint64, machine_mode, rtx, bool); -extern rtx extract_bit_field (rtx, poly_uint64, poly_uint64, int, rtx, +extern rtx extract_bit_field (rtx, poly_uint64, poly_uint64, int, + poly_uint64, poly_uint64, rtx, machine_mode, machine_mode, bool, rtx *); extern rtx extract_low_bits (machine_mode, machine_mode, rtx); extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int, bool = false); diff --git a/gcc/expr.c b/gcc/expr.c index c19e5c560f3..7102fa96cef 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -2288,6 +2288,8 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, poly_int64 bytepos = rtx_to_poly_int64 (XEXP (XVECEXP (dst, 0, i), 1)); poly_int64 bytelen = GET_MODE_SIZE (mode); poly_int64 shift = 0; + poly_int64 bitregion_start = 0; + poly_int64 bitregion_end = 0; /* Handle trailing fragments that run over the size of the struct. It's the target's responsibility to make sure that the fragment @@ -2308,7 +2310,12 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, ) shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT; bytelen = ssize - bytepos; - gcc_assert (maybe_gt (bytelen, 0)); + if (MEM_P (orig_src) + && CAPABILITY_MODE_P (GET_MODE (XEXP (orig_src, 0)))) + { + bitregion_start = bytepos * BITS_PER_UNIT; + bitregion_end = (bytepos + bytelen) * BITS_PER_UNIT - 1; + } } /* If we won't be loading directly from memory, protect the real source @@ -2364,8 +2371,9 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, && (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))) tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT, subpos * BITS_PER_UNIT, - 1, NULL_RTX, mode, mode, false, - NULL); + 1, bitregion_start, bitregion_end, + NULL_RTX, mode, mode, + false, NULL); } else { @@ -2375,8 +2383,9 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, mem = assign_stack_temp (GET_MODE (src), slen); emit_move_insn (mem, src); tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT, - 0, 1, NULL_RTX, mode, mode, false, - NULL); + 0, 1, bitregion_start, bitregion_end, + NULL_RTX, mode, mode, + false, NULL); } } /* FIXME: A SIMD parallel will eventually lead to a subreg of a @@ -2416,8 +2425,9 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, tmps[i] = src; else tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT, - bytepos * BITS_PER_UNIT, 1, NULL_RTX, - mode, mode, false, NULL); + bytepos * BITS_PER_UNIT, 1, + bitregion_start, bitregion_end, + NULL_RTX, mode, mode, false, NULL); if (maybe_ne (shift, 0)) tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i], @@ -2881,7 +2891,7 @@ copy_blkmode_from_reg (rtx target, rtx srcreg, tree type) bitpos for the destination store (left justified). */ store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, 0, 0, copy_mode, extract_bit_field (src, bitsize, - xbitpos % BITS_PER_WORD, 1, + xbitpos % BITS_PER_WORD, 1, 0, 0, NULL_RTX, copy_mode, copy_mode, false, NULL), false); @@ -2983,7 +2993,7 @@ copy_blkmode_to_reg (machine_mode mode_in, tree src) store_bit_field (dst_word, bitsize, xbitpos % BITS_PER_WORD, 0, 0, word_mode, extract_bit_field (src_word, bitsize, - bitpos % BITS_PER_WORD, 1, + bitpos % BITS_PER_WORD, 1, 0, 0, NULL_RTX, word_mode, word_mode, false, NULL), false); @@ -3433,7 +3443,7 @@ read_complex_part (rtx cplx, bool imag_p) } return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, - true, NULL_RTX, imode, imode, false, NULL); + true, 0, 0, NULL_RTX, imode, imode, false, NULL); } \f /* A subroutine of emit_move_insn_1. Yet another lowpart generator. @@ -7380,7 +7390,8 @@ store_field (rtx target, poly_int64 bitsize, poly_int64 bitpos, if (GET_MODE (temp) == BLKmode && known_le (bitsize, BITS_PER_WORD)) { temp_mode = smallest_int_mode_for_size (bitsize); - temp = extract_bit_field (temp, bitsize, 0, 1, NULL_RTX, temp_mode, + temp = extract_bit_field (temp, bitsize, 0, 1, bitregion_start, + bitregion_end, NULL_RTX, temp_mode, temp_mode, false, NULL); } @@ -8697,7 +8708,7 @@ expand_misaligned_mem_ref (rtx temp, machine_mode mode, int unsignedp, } else if (targetm.slow_unaligned_access (mode, align)) temp = extract_bit_field (temp, GET_MODE_BITSIZE (mode), - 0, unsignedp, target, + 0, unsignedp, 0, 0, target, mode, mode, false, alt_rtl); return temp; } @@ -11025,6 +11036,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, &unsignedp, &reversep, &volatilep); rtx orig_op0, memloc; bool clear_mem_expr = false; + poly_uint64 bitregion_start = 0; + poly_uint64 bitregion_end = 0; /* If we got back the original object, something is wrong. Perhaps we are evaluating an expression too early. In any event, don't @@ -11046,6 +11059,24 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier, NULL, true); + /* For capability targets there is a need to limit the memory access to + the bounds of the struct or union. For bit fields in a struct use + get_bit_range and for other cases fall back to a sensible alternative + based on MEM_SIZE. This needs to be done here, before + op0 gets modified in a way that increases the MEM_SIZE. */ + if (MEM_P (op0) && CAPABILITY_MODE_P (GET_MODE (XEXP (op0, 0))) + && TREE_CODE (exp) == COMPONENT_REF + && DECL_BIT_FIELD_TYPE (TREE_OPERAND (exp, 1)) + && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (exp, 1))) + get_bit_range (&bitregion_start, &bitregion_end, exp, &bitpos, + &offset); + else if (MEM_P (op0) && MEM_SIZE_KNOWN_P (op0) + && CAPABILITY_MODE_P (GET_MODE (XEXP (op0, 0)))) + { + bitregion_start = force_align_down (bitpos, BITS_PER_UNIT); + bitregion_end = MEM_SIZE (op0) * BITS_PER_UNIT - 1; + } + /* If the field has a mode, we want to access it in the field's mode, not the computed mode. If a MEM has VOIDmode (external with incomplete type), @@ -11194,6 +11225,9 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, && MEM_ALIGN (op0) >= GET_MODE_ALIGNMENT (mode1)) { op0 = adjust_address (op0, mode1, bytepos); + bitregion_start = 0; + if (known_ge (bitregion_end, poly_uint64 (bitpos))) + bitregion_end -= bitpos; bitpos = 0; } @@ -11328,6 +11362,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, gcc_checking_assert (known_ge (bitpos, 0)); op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp, + bitregion_start, bitregion_end, (modifier == EXPAND_STACK_PARM ? NULL_RTX : target), ext_mode, ext_mode, reversep, alt_rtl); @@ -11566,7 +11601,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, /* If the output type is a bit-field type, do an extraction. */ else if (reduce_bit_field) return extract_bit_field (op0, TYPE_PRECISION (type), 0, - TYPE_UNSIGNED (type), NULL_RTX, + TYPE_UNSIGNED (type), 0, 0, NULL_RTX, mode, mode, false, NULL); /* As a last resort, spill op0 to memory, and reload it in a different mode. */ diff --git a/gcc/function.c b/gcc/function.c index 8fb6a4cfb27..760b038af0e 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3322,7 +3322,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, else rtl = parmreg = extract_bit_field (validated_mem, GET_MODE_BITSIZE (promoted_nominal_mode), 0, - unsignedp, parmreg, + unsignedp, 0, 0, parmreg, promoted_nominal_mode, VOIDmode, false, NULL); } else
reply other threads:[~2022-02-28 12:08 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220228120804.D13473858430@sourceware.org \ --to=matmal01@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).