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