aboutsummaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorBernd Edlinger <bernd.edlinger@hotmail.de>2013-12-11 17:09:17 +0000
committerBernd Edlinger <edlinger@gcc.gnu.org>2013-12-11 17:09:17 +0000
commitebb99f967b8d4b1c23dfba167e16dd2c6786633a (patch)
tree4ba21c39b0d8a3c5a6bae82fe8579f445e23044e /gcc/expmed.c
parent6f4e9cf84204e690b7c32060f8eb7d978bfcf2ca (diff)
downloadgcc-ebb99f967b8d4b1c23dfba167e16dd2c6786633a.zip
gcc-ebb99f967b8d4b1c23dfba167e16dd2c6786633a.tar.gz
gcc-ebb99f967b8d4b1c23dfba167e16dd2c6786633a.tar.bz2
re PR middle-end/59134 (infinite loop between store_fixed_bit_field and store_split_bit_field with STRICT_ALIGNMENT)
2013-12-11 Bernd Edlinger <bernd.edlinger@hotmail.de> PR middle-end/59134 * expmed.c (store_bit_field): Use narrow_bit_field_mem and store_fixed_bit_field_1 for -fstrict-volatile-bitfields. (store_fixed_bit_field): Split up. Call store_fixed_bit_field_1 to do the real work. (store_fixed_bit_field_1): New function. (store_split_bit_field): Limit the unit size to the memory mode size, to prevent recursion. testsuite: * gcc.c-torture/compile/pr59134.c: New test. * gnat.dg/misaligned_volatile.adb: New test. From-SVN: r205898
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r--gcc/expmed.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 08ad9e0..3a6c919 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -48,6 +48,9 @@ static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
rtx);
+static void store_fixed_bit_field_1 (rtx, unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ rtx);
static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
@@ -948,10 +951,16 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
emit_move_insn (str_rtx, value);
}
else
- /* Explicitly override the C/C++ memory model; ignore the
- bit range so that we can do the access in the mode mandated
- by -fstrict-volatile-bitfields instead. */
- store_fixed_bit_field (str_rtx, bitsize, bitnum, 0, 0, value);
+ {
+ str_rtx = narrow_bit_field_mem (str_rtx, fieldmode, bitsize, bitnum,
+ &bitnum);
+ /* Explicitly override the C/C++ memory model; ignore the
+ bit range so that we can do the access in the mode mandated
+ by -fstrict-volatile-bitfields instead. */
+ store_fixed_bit_field_1 (str_rtx, bitsize, bitnum,
+ value);
+ }
+
return;
}
@@ -994,9 +1003,6 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
rtx value)
{
enum machine_mode mode;
- rtx temp;
- int all_zero = 0;
- int all_one = 0;
/* There is a case not handled here:
a structure with a known alignment of just a halfword
@@ -1026,6 +1032,23 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum);
}
+ store_fixed_bit_field_1 (op0, bitsize, bitnum, value);
+ return;
+}
+
+/* Helper function for store_fixed_bit_field, stores
+ the bit field always using the MODE of OP0. */
+
+static void
+store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
+ unsigned HOST_WIDE_INT bitnum,
+ rtx value)
+{
+ enum machine_mode mode;
+ rtx temp;
+ int all_zero = 0;
+ int all_one = 0;
+
mode = GET_MODE (op0);
gcc_assert (SCALAR_INT_MODE_P (mode));
@@ -1134,6 +1157,12 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
else
unit = MIN (MEM_ALIGN (op0), BITS_PER_WORD);
+ /* If OP0 is a memory with a mode, then UNIT must not be larger than
+ OP0's mode as well. Otherwise, store_fixed_bit_field will call us
+ again, and we will mutually recurse forever. */
+ if (MEM_P (op0) && GET_MODE_BITSIZE (GET_MODE (op0)) > 0)
+ unit = MIN (unit, GET_MODE_BITSIZE (GET_MODE (op0)));
+
/* If VALUE is a constant other than a CONST_INT, get it into a register in
WORD_MODE. If we can do this using gen_lowpart_common, do so. Note
that VALUE might be a floating-point constant. */