From b6dd42a9a8ec56b5badc59c78f69760048914da4 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Wed, 1 Apr 2015 16:09:48 +0000 Subject: [PATCH] expmed.c (strict_volatile_bitfield_p): Check that the access will not cross a MODESIZE boundary. gcc: 2015-04-01 Bernd Edlinger * expmed.c (strict_volatile_bitfield_p): Check that the access will not cross a MODESIZE boundary. (store_bit_field, extract_bit_field): Added assertions in the strict volatile bitfields code path. testsuite: 2015-04-01 Bernd Edlinger * gcc.dg/pr23623.c: Added aligned attribute. * gcc.dg/20141029-1.c: Likewise. * gcc.dg/20150306-1.c: New test. From-SVN: r221809 --- gcc/ChangeLog | 7 +++++++ gcc/expmed.c | 29 ++++++++++++++++++++--------- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.dg/20141029-1.c | 2 +- gcc/testsuite/gcc.dg/20150306-1.c | 20 ++++++++++++++++++++ gcc/testsuite/gcc.dg/pr23623.c | 6 +++--- 6 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/20150306-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 11a79db10a2..47c0f22a735 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-04-01 Bernd Edlinger + + * expmed.c (strict_volatile_bitfield_p): Check that the access will + not cross a MODESIZE boundary. + (store_bit_field, extract_bit_field): Added assertions in the + strict volatile bitfields code path. + 2015-04-01 Max Ostapenko PR target/65624 diff --git a/gcc/expmed.c b/gcc/expmed.c index e0b2619034d..6327629d458 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -472,9 +472,13 @@ strict_volatile_bitfield_p (rtx op0, unsigned HOST_WIDE_INT bitsize, return false; /* Check for cases of unaligned fields that must be split. */ - if (bitnum % BITS_PER_UNIT + bitsize > modesize - || (STRICT_ALIGNMENT - && bitnum % GET_MODE_ALIGNMENT (fieldmode) + bitsize > modesize)) + if (bitnum % modesize + bitsize > modesize) + return false; + + /* The memory must be sufficiently aligned for a MODESIZE access. + This condition guarantees, that the memory access will not + touch anything after the end of the structure. */ + if (MEM_ALIGN (op0) < modesize) return false; /* Check for cases where the C++ memory model applies. */ @@ -973,13 +977,15 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, fieldmode, bitregion_start, bitregion_end)) { - /* Storing any naturally aligned field can be done with a simple - store. For targets that support fast unaligned memory, any - naturally sized, unit aligned field can be done directly. */ + /* Storing of a full word can be done with a simple store. + We know here that the field can be accessed with one single + instruction. For targets that support unaligned memory, + an unaligned access may be necessary. */ if (bitsize == GET_MODE_BITSIZE (fieldmode)) { str_rtx = adjust_bitfield_address (str_rtx, fieldmode, bitnum / BITS_PER_UNIT); + gcc_assert (bitnum % BITS_PER_UNIT == 0); emit_move_insn (str_rtx, value); } else @@ -988,6 +994,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, str_rtx = narrow_bit_field_mem (str_rtx, fieldmode, bitsize, bitnum, &bitnum); + gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (fieldmode)); temp = copy_to_reg (str_rtx); if (!store_bit_field_1 (temp, bitsize, bitnum, 0, 0, fieldmode, value, true)) @@ -1790,17 +1797,21 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, mode1, 0, 0)) { - /* Extraction of a full MODE1 value can be done with a load as long as - the field is on a byte boundary and is sufficiently aligned. */ - if (bitsize == GET_MODE_BITSIZE(mode1)) + /* Extraction of a full MODE1 value can be done with a simple load. + We know here that the field can be accessed with one single + instruction. For targets that support unaligned memory, + an unaligned access may be necessary. */ + if (bitsize == GET_MODE_BITSIZE (mode1)) { rtx result = adjust_bitfield_address (str_rtx, mode1, bitnum / BITS_PER_UNIT); + gcc_assert (bitnum % BITS_PER_UNIT == 0); return convert_extracted_bit_field (result, mode, tmode, unsignedp); } str_rtx = narrow_bit_field_mem (str_rtx, mode1, bitsize, bitnum, &bitnum); + gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (mode1)); str_rtx = copy_to_reg (str_rtx); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 399f9ccad37..9f8e0b75bab 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-04-01 Bernd Edlinger + + * gcc.dg/pr23623.c: Added aligned attribute. + * gcc.dg/20141029-1.c: Likewise. + * gcc.dg/20150306-1.c: New test. + 2015-04-01 Marek Polacek PR c++/65554 diff --git a/gcc/testsuite/gcc.dg/20141029-1.c b/gcc/testsuite/gcc.dg/20141029-1.c index b25af576967..1d18a1b8ac3 100644 --- a/gcc/testsuite/gcc.dg/20141029-1.c +++ b/gcc/testsuite/gcc.dg/20141029-1.c @@ -14,7 +14,7 @@ struct system_periph { unsigned short :8; } BIT; } ALL; -}; +} __attribute__((aligned(2))); void foo() diff --git a/gcc/testsuite/gcc.dg/20150306-1.c b/gcc/testsuite/gcc.dg/20150306-1.c new file mode 100644 index 00000000000..55caf3b93ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/20150306-1.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-require-effective-target size32plus } */ +/* { dg-options "-fstrict-volatile-bitfields" } */ + +struct s +{ + char x : 8; + unsigned int y : 31; +} __attribute__((packed)); + +volatile struct s global; + +int +main () +{ + global.y = 0x7FFFFFFF; + if (global.y != 0x7FFFFFFF) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr23623.c b/gcc/testsuite/gcc.dg/pr23623.c index 7ba1470182d..e076b600335 100644 --- a/gcc/testsuite/gcc.dg/pr23623.c +++ b/gcc/testsuite/gcc.dg/pr23623.c @@ -10,19 +10,19 @@ extern struct { unsigned int b : 1; unsigned int : 31; -} bf1; +} __attribute__((aligned(4))) bf1; extern volatile struct { unsigned int b : 1; unsigned int : 31; -} bf2; +} __attribute__((aligned(4))) bf2; extern struct { volatile unsigned int b : 1; volatile unsigned int : 31; -} bf3; +} __attribute__((aligned(4))) bf3; void writeb(void) { -- 2.30.2