Hi, I get a piece of code to be compiled by gcc with the combined '-Os -mregparm=3' options to generate the x86 32-bit codes, and I found gcc created broken codes.
The test codes that can be used to trigger this issue: (save the following to test.c.) typedef struct { int a; int b; } TEST_INFO; typedef struct { int a; } PCALL_PARAM; typedef int (*PCALL)(PCALL_PARAM *); extern TEST_INFO * dont_care(void); #undef WORKAROUND int test (TEST_INFO *info, int d) { PCALL pcall; PCALL_PARAM params; PCALL_PARAM *params_ptr; int status; TEST_INFO *r; if (!info) { r = (TEST_INFO *)dont_care(); } else { r = info; } pcall = (PCALL)(r->a + r->b); params.a = d; #ifdef WORKAROUND status = pcall (¶ms); #endif params_ptr = ¶ms; asm volatile ( "pushl %1;" "call *%%eax;" "addl $4, %%esp;" : "=a"(status) : "m"(params_ptr), "a"(pcall) ); return status; } The gcc command I am using to compile the file: $ gcc -v -Os -mregparm=3 -march=i386 -m32 -c -o test.o test.c Using built-in specs. COLLECT_GCC=gcc Target: x86_64-CentOS-linux Configured with: ../configure --prefix=/opt/centos/devtoolset-1.1/root/usr --mandir=/opt/centos/devtoolset-1.1/root/usr/share/man --infodir=/opt/centos/devtoolset-1.1/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --disable-build-with-cxx --disable-build-poststage1-with-cxx --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --disable-gnu-unique-object --enable-linker-build-id --enable-languages=c,c++,fortran,lto --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --disable-libgcj --with-gmp=/home/centos/rpm/BUILD/gcc-4.7.2-20121015/obj-x86_64-CentOS-linux/gmp-install --with-mpfr=/home/centos/rpm/BUILD/gcc-4.7.2-20121015/obj-x86_64-CentOS-linux/mpfr-install --with-ppl=/home/centos/rpm/BUILD/gcc-4.7.2-20121015/obj-x86_64-CentOS-linux/ppl-install --with-cloog=/home/centos/rpm/BUILD/gcc-4.7.2-20121015/obj-x86_64-CentOS-linux/cloog-install --with-mpc=/home/centos/rpm/BUILD/gcc-4.7.2-20121015/obj-x86_64-CentOS-linux/mpc-install --with-tune=generic --with-arch_32=i586 --build=x86_64-CentOS-linux Thread model: posix gcc version 4.7.2 20121015 (Red Hat 4.7.2-5) (GCC) COLLECT_GCC_OPTIONS='-v' '-Os' '-mregparm=3' '-march=i386' '-m32' '-c' '-o' 'test.o' /opt/centos/devtoolset-1.1/root/usr/libexec/gcc/x86_64-CentOS-linux/4.7.2/cc1 -quiet -v -imultilib 32 test.c -quiet -dumpbase test.c -mregparm=3 -march=i386 -m32 -auxbase-strip test.o -Os -version -o /tmp/ccrfMdFf.s GNU C (GCC) version 4.7.2 20121015 (Red Hat 4.7.2-5) (x86_64-CentOS-linux) compiled by GNU C version 4.7.2 20121015 (Red Hat 4.7.2-5), GMP version 4.3.1, MPFR version 2.4.1, MPC version 0.8.1 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring nonexistent directory "/opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/4.7.2/include-fixed" ignoring nonexistent directory "/opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/4.7.2/../../../../x86_64-CentOS-linux/include" #include "..." search starts here: #include <...> search starts here: /opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/4.7.2/include /usr/local/include /opt/centos/devtoolset-1.1/root/usr/include /usr/include End of search list. GNU C (GCC) version 4.7.2 20121015 (Red Hat 4.7.2-5) (x86_64-CentOS-linux) compiled by GNU C version 4.7.2 20121015 (Red Hat 4.7.2-5), GMP version 4.3.1, MPFR version 2.4.1, MPC version 0.8.1 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 08198519a1e798dc5da060bad8011478 COLLECT_GCC_OPTIONS='-v' '-Os' '-mregparm=3' '-march=i386' '-m32' '-c' '-o' 'test.o' /opt/centos/devtoolset-1.1/root/usr/libexec/gcc/x86_64-CentOS-linux/4.7.2/as -v --32 -o test.o /tmp/ccrfMdFf.s GNU assembler version 2.23.51.0.3 (x86_64-CentOS-linux) using BFD version version 2.23.51.0.3-3.el5 20120918 COMPILER_PATH=/opt/centos/devtoolset-1.1/root/usr/libexec/gcc/x86_64-CentOS-linux/4.7.2/:/opt/centos/devtoolset-1.1/root/usr/libexec/gcc/x86_64-CentOS-linux/4.7.2/:/opt/centos/devtoolset-1.1/root/usr/libexec/gcc/x86_64-CentOS-linux/:/opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/4.7.2/:/opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/ LIBRARY_PATH=/opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/4.7.2/32/:/opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/4.7.2/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/4.7.2/:/opt/centos/devtoolset-1.1/root/usr/lib/gcc/x86_64-CentOS-linux/4.7.2/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-Os' '-mregparm=3' '-march=i386' '-m32' '-c' '-o' 'test.o' Using objdump to disassemble the test.o $ objdump -D test.o > asm.txt And the generated codes are: 00000000 <test>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 18 sub $0x18,%esp 6: 85 c0 test %eax,%eax 8: 75 05 jne f <test+0xf> a: e8 fc ff ff ff call b <test+0xb> f: 8b 10 mov (%eax),%edx 11: 03 50 04 add 0x4(%eax),%edx 14: 8d 45 f0 lea -0x10(%ebp),%eax 17: 89 45 f4 mov %eax,-0xc(%ebp) 1a: 89 d0 mov %edx,%eax 1c: ff 75 f4 pushl -0xc(%ebp) 1f: ff d0 call *%eax 21: 83 c4 04 add $0x4,%esp 24: c9 leave 25: c3 ret See the edx gets overwritten at address 0xf 'mov (%eax),%edx' while edx holds the 2nd parameter of function test when given option '-mregparm=3'. I believe this is a bug. Could someone confirm this? Thanks, Regards, Bin