http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51643
Bug #: 51643 Summary: Incorrect code produced for tail-call of weak function with -O2/-O3 option Classification: Unclassified Product: gcc Version: 4.6.2 Status: UNCONFIRMED Severity: major Priority: P3 Component: rtl-optimization AssignedTo: unassig...@gcc.gnu.org ReportedBy: sip...@gmail.com A tail-call of weak function produces incorrect code, compiled with -O2 or -O3. Target: arm-eabi Version: GCC 4.6.2 and 4.6.1 ***** Test case: t00x1.c <<<<< extern void __attribute__((weak)) wfunc(void); void main(void) { wfunc(); // tail weak call fails!!! // __asm__ volatile ("nop":::"memory"); // workaround } >>>>> $ /opt/arm/gnuarm-4.6.2/bin/arm-eabi-gcc -c -S -o t00x1.S -O2 t00x1.c ***** Contents of t00x1.S: .file "t00x1.c" .section .text.startup,"ax",%progbits .align 2 .global main .type main, %function main: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. b wfunc @@@@ <<< Will be replaced by "NOP" in linker!! @@@@ so, no return sequence! .size main, .-main .weak wfunc .ident "GCC: (GNU) 4.6.2" ***** Disassembled (objdump) code: t00x1.lst: 00000240 <main>: 240: e1a00000 nop ; (mov r0, r0) @@@@ really, NOP 00000244 <__do_global_dtors_aux>: 244: e92d4010 push {r4, lr} 248: e59f4028 ldr r4, [pc, #40] ; 278 ....... ****** Call to function "wfunc" was converted to NOP by linker, as expected. As a result, no return sequence from main(), falling througt to next code line. For reference: the same program compiled with -O1 ******* .file "t00x1.c" .text .align 2 .global main .type main, %function main: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 stmfd sp!, {r3, lr} bl wfunc ldmfd sp!, {r3, pc} .size main, .-main .weak wfunc .ident "GCC: (GNU) 4.6.2" Code with workaround, compiled with -O2 correct: $ /opt/arm/gnuarm-4.6.2/bin/arm-eabi-gcc -c -S -o t00x1.S -O2 t00x1.c ******* .file "t00x1.c" .section .text.startup,"ax",%progbits .align 2 .global main .type main, %function main: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 stmfd sp!, {r3, lr} bl wfunc @ 5 "t00x1.c" 1 nop @ 0 "" 2 ldmfd sp!, {r3, pc} .size main, .-main .weak wfunc .ident "GCC: (GNU) 4.6.2" ******* Compiler options: $ /opt/arm/gnuarm-4.6.2/bin/arm-eabi-gcc -v Using built-in specs. COLLECT_GCC=/opt/arm/gnuarm-4.6.2/bin/arm-eabi-gcc COLLECT_LTO_WRAPPER=/opt/arm/gnuarm-4.6.2/libexec/gcc/arm-eabi/4.6.2/lto-wrapper Target: arm-eabi Configured with: ../../src/gcc-4.6.2/configure --target=arm-eabi --prefix=/opt/arm/gnuarm-4.6.2 --enable-multilib --enable-interwork --enable-biendian --enable-fpu --with-newlib --with-gnu-ld --with-gnu-as --disable-nls --disable-shared --with-arch=armv5te --with-fpu=vfp --with-float=softfp --with-abi=aapcs-linux --enable-lto --enable-languages=c,c++ --disable-threads --enable-ppl --enable-cloog --enable-gmp --enable-mpfr --enable-lto -with-headers=/opt/arm/gnuarm-4.6.2/arm-eabi/include Thread model: single gcc version 4.6.2 (GCC)