https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91812

            Bug ID: 91812
           Summary: GCC ignores volatile modifier
           Product: gcc
           Version: 8.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: fuchedzhy at google dot com
  Target Milestone: ---

GCC appears to ignore volatile modifier sometimes. C is probably wrong
component for the bug, but I'm not sure where else to put it.

$ arm-linux-gnueabi-gcc-8 -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabi-gcc-8
COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabi/8/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../src/configure -v --with-pkgversion='Debian 8.3.0-6'
--with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs
--enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr
--with-gcc-major-version-only --program-suffix=-8 --enable-shared
--enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext
--enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/
--enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm
--disable-libquadmath --disable-libquadmath-support --enable-plugin
--enable-default-pie --with-system-zlib --with-target-system-zlib
--enable-multiarch --disable-sjlj-exceptions --with-arch=armv5te
--with-float=soft --disable-werror --enable-checking=release
--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-linux-gnueabi
--program-prefix=arm-linux-gnueabi- --includedir=/usr/arm-linux-gnueabi/include
Thread model: posix
gcc version 8.3.0 (Debian 8.3.0-6) 

This is a minimal example I could come up with:

volatile unsigned register1;
volatile unsigned register2;

void busy_wait_for_register(int x) {
  volatile unsigned* ptr;
  switch(x) {
    case 0x1111:
      ptr = &register1;
      break;

    case 0x2222:
      ptr = &register2;
      break;

    default:
      return;
  }
  while (*ptr) {}
}

If compiled with following command:
$ arm-linux-gnueabi-gcc-8 -mcpu=cortex-m7 -Os -c main.c

Produces following binary:
$ arm-linux-gnueabi-objdump -d main.o

main.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <busy_wait_for_register>:
   0:   f241 1211       movw    r2, #4369       ; 0x1111
   4:   4b08            ldr     r3, [pc, #32]   ; (28
<busy_wait_for_register+0x28>)
   6:   4290            cmp     r0, r2
   8:   447b            add     r3, pc
   a:   d004            beq.n   16 <busy_wait_for_register+0x16>
   c:   f242 2222       movw    r2, #8738       ; 0x2222
  10:   4290            cmp     r0, r2
  12:   d006            beq.n   22 <busy_wait_for_register+0x22>
  14:   4770            bx      lr
  16:   4a05            ldr     r2, [pc, #20]   ; (2c
<busy_wait_for_register+0x2c>)
  18:   589b            ldr     r3, [r3, r2]
  1a:   681b            ldr     r3, [r3, #0]
  1c:   2b00            cmp     r3, #0
  1e:   d1fd            bne.n   1c <busy_wait_for_register+0x1c>
  20:   4770            bx      lr
  22:   4a03            ldr     r2, [pc, #12]   ; (30
<busy_wait_for_register+0x30>)
  24:   e7f8            b.n     18 <busy_wait_for_register+0x18>
  26:   bf00            nop
  28:   0000001c        .word   0x0000001c
        ...

Note that generated while loop instructions:
  1c:   2b00            cmp     r3, #0
  1e:   d1fd            bne.n   1c <busy_wait_for_register+0x1c>
never reload the register making this effectively an infinite loop.
I believe volatile keyword should have prevented that.

Reply via email to