http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58259
Bug ID: 58259 Summary: PowerPC: Atomic flag test and set generates NULL pointer read and write Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: sebastian.hu...@embedded-brains.de The GCC C compiler generates a NULL pointer read and write for the atomic flag test and set method in GCC 4.7, 4.8 and 4.9. The GCC C++ compiler doesn't have this problem. C test case: #include <stdatomic.h> _Bool test_and_set(atomic_flag *flag) { return atomic_flag_test_and_set_explicit(flag, memory_order_acquire); } C++ test case: #include <atomic> bool test_and_set(std::atomic_flag &flag) { return flag.test_and_set(std::memory_order_acquire); } GCC assembler output: powerpc-eabi-gcc-4.7.0 -std=c11 -Wall -Wextra -O2 -S test.c && cat test.s .file "test.c" .section ".text" .align 2 .globl test_and_set .type test_and_set, @function test_and_set: li 10,0 rlwinm 9,3,3,27,28 lbz 5,0(10) <--- HERE IS THE NULL POINTER READ xori 9,9,24 li 7,255 li 6,1 rlwinm 3,3,0,0,29 slw 7,7,9 slw 5,5,9 slw 6,6,9 .L2: lwarx 10,0,3 and 8,10,7 cmpw 0,8,5 andc 8,10,7 or 8,8,6 bne- 0,.L3 stwcx. 8,0,3 bne- 0,.L2 .L3: isync srw 10,10,9 li 9,0 mfcr 3 rlwinm 3,3,3,1 stb 10,0(9) <--- HERE IS THE NULL POINTER WRITE blr .size test_and_set, .-test_and_set .ident "GCC: (GNU) 4.7.0 20120202 (experimental) [master revision 022fc2d:bffd767:fd457cef14f3bc6673e90a2de80005feea743ab7]" powerpc-eabi-gcc -std=c11 -Wall -Wextra -O2 -S test.c && cat test.s .file "test.c" .section ".text" .align 2 .globl test_and_set .type test_and_set, @function test_and_set: li 9,0 li 7,255 lbz 5,0(9) rlwinm 9,3,3,27,28 xori 9,9,24 li 6,1 rlwinm 3,3,0,0,29 slw 7,7,9 slw 5,5,9 slw 6,6,9 .L2: lwarx 10,0,3 and 4,10,7 andc 8,10,7 cmpw 0,4,5 or 8,8,6 bne- 0,.L3 stwcx. 8,0,3 bne- 0,.L2 .L3: isync srw 10,10,9 li 9,0 stb 10,0(9) mfcr 3 rlwinm 3,3,3,1 blr .size test_and_set, .-test_and_set .ident "GCC: (GNU) 4.9.0 20130828 (experimental) [master revision 022fc2d:bffd767:fd457cef14f3bc6673e90a2de80005feea743ab7]" powerpc-eabi-g++ -std=c++11 -Wall -Wextra -O2 -S test.cc && cat test.s .file "test.cc" .section ".text" .align 2 .globl _Z12test_and_setRSt11atomic_flag .type _Z12test_and_setRSt11atomic_flag, @function _Z12test_and_setRSt11atomic_flag: .LFB326: .cfi_startproc rlwinm 9,3,3,27,28 li 6,255 xori 9,9,24 li 7,1 rlwinm 8,3,0,0,29 slw 6,6,9 slw 7,7,9 .L2: lwarx 3,0,8 andc 10,3,6 or 10,10,7 stwcx. 10,0,8 bne- 0,.L2 isync srw 3,3,9 rlwinm 3,3,0,0xff blr .cfi_endproc .LFE326: .size _Z12test_and_setRSt11atomic_flag, .-_Z12test_and_setRSt11atomic_flag .ident "GCC: (GNU) 4.9.0 20130828 (experimental) [master revision 022fc2d:bffd767:fd457cef14f3bc6673e90a2de80005feea743ab7]" The ARMv7 architecture has a very similar atomic model and GCC generates valid code: arm-eabi-gcc -march=armv7-a -std=c11 -Wall -Wextra -O2 -S test.c && cat test.s .arch armv7-a .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 1 .eabi_attribute 30, 2 .eabi_attribute 34, 1 .eabi_attribute 18, 4 .file "test.c" .text .align 2 .global test_and_set .type test_and_set, %function test_and_set: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. mov r3, #0 mov r1, #1 ldrb r2, [r3] @ zero_extendqisi2 .L2: ldrexb r3, [r0] cmp r3, r2 bne .L3 strexb ip, r1, [r0] cmp ip, #0 bne .L2 .L3: mov r2, #0 dmb sy movne r0, #0 moveq r0, #1 strb r3, [r2] bx lr .size test_and_set, .-test_and_set .ident "GCC: (GNU) 4.8.2 20130807 (prerelease) [master revision 022fc2d:bffd767:fd457cef14f3bc6673e90a2de80005feea743ab7]" Interestingly the code generated by the C++ compiler is much better for both ARM and PowerPC. arm-eabi-g++ -march=armv7-a -std=c++11 -Wall -Wextra -O2 -S test.cc && cat test.s .arch armv7-a .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 1 .eabi_attribute 30, 2 .eabi_attribute 34, 1 .eabi_attribute 18, 4 .file "test.cc" .text .align 2 .global _Z12test_and_setRSt11atomic_flag .type _Z12test_and_setRSt11atomic_flag, %function _Z12test_and_setRSt11atomic_flag: .fnstart .LFB326: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. mov r2, #1 .L2: ldrexb r3, [r0] strexb r1, r2, [r0] cmp r1, #0 bne .L2 dmb sy uxtb r0, r3 bx lr .cantunwind .fnend .size _Z12test_and_setRSt11atomic_flag, .-_Z12test_and_setRSt11atomic_flag .ident "GCC: (GNU) 4.8.2 20130807 (prerelease) [master revision 022fc2d:bffd767:fd457cef14f3bc6673e90a2de80005feea743ab7]"