From n6il@ocs.net Fri Jun 11 10:05:05 2010 Date: Fri, 11 Jun 2010 10:03:56 -0700 From: Michael Furman Reply-To: Cameron Berkenpas To: Jeff Furman Subject: Re: possible gcc code generator bug? I have a bunch of information that should assist you in debugging this issue. I would carefully read through the GCC manual, possibly sections 3.10 or 3.17.11. http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/index.html#Top Request an assembly listing with high level code interspersed and turn off optimizations: gcc -O0 -g -Wa,-ahl ... In case you need refreshers on ATT asm syntax here are two helpful links: http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html http://sig9.com/articles/att-syntax Also remember that IntelArchitecture-32bit ABI states that registers are global and arguments are passed on the stack. Start reading at pg 3-9: http://www.sco.com/developers/devspecs/abi386-4.pdf movl w, %ebx <<<<<<<<<<<<<<< eager load of w is bug, given volatile w call cons <<<<<<<<<<<<<<< side effect of cons changes w movl %eax, car(,%ebx,4) Cons takes no arguments, so you see no mov SRC, (%esp) before call cons. How can cons() change w? Is it a global? Wouldn't the bug actually be that cons uses %ebx and doesn't save it? My c0 compiler does do some work in this area but it's for SPARC with register argument passing and register windows. For x86 you generally assume that %eax, %ebx, %ecx, and %edx are modified across a call since they have special purposes and this is why the ABI specifies that the stack is used to pass arguments-- %ecx used for counting (loop, rep), %ebx and/or %edx are commonly used as index registers (your code uses %eax), mul and div require %eax and %edx at a minimum. Also I found the following article describing the use of volatile. It would seem after reading it that it's indeed a bug, but whether it's because volatile was forgotten somewhere or %ebx wasn't saved requires more investigation. http://www.netrino.com/Embedded-Systems/How-To/C-Volatile-Keyword On Jun 10, 2010, at 2:56 PM, Jeff Furman wrote: > Two versions of generated code-- first shows bug, second shows crude fix: > > compiler info: > gcc -v > Reading specs from /usr/lib/gcc/i686-pc-linux-gnu/3.4.5/specs > Configured with: /var/tmp/portage/gcc-3.4.5/work/gcc-3.4.5/configure > --prefix=/usr --bindir=/usr/i686-pc-linux-gnu/gcc-bin/3.4.5 > --includedir=/usr/lib/gcc/i686-pc-linux-gnu/3.4.5/include > --datadir=/usr/share/gcc-data/i686-pc-linux-gnu/3.4.5 > --mandir=/usr/share/gcc-data/i686-pc-linux-gnu/3.4.5/man > --infodir=/usr/share/gcc-data/i686-pc-linux-gnu/3.4.5/info > --with-gxx-include-dir=/usr/lib/gcc/i686-pc-linux-gnu/3.4.5/include/g++-v3 > --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-altivec > --enable-nls --without-included-gettext --with-system-zlib --disable-checking > --disable-werror --disable-libunwind-exceptions --disable-multilib > --disable-libgcj --enable-languages=c,c++,objc,f77 --enable-shared > --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu > Thread model: posix > gcc version 3.4.5 (Gentoo 3.4.5, ssp-3.4.5-1.0, pie-8.7.9) > > > ,,, > volatile int car[cnssz+1],cdr[cnssz+1],atom[tagsz+1],num[tagsz+1],markr[tagsz+1]; > volatile int s,e,c,d; > volatile int w; > volatile int t,f,nil,ff; > ... > case 13: > printroots(3); > w = cons(); > printroots(4); > /*tmptmp = cons();*/ > car[w]= /*tmptmp */cons(); > printroots(5); > car[car[w]]=car[s]; > cdr[car[w]]=car[cdr[s]]; > cdr[w]=cdr[cdr[s]]; > s=w; > c = cdr[c]; > goto l1000; > ... > > generated code-- .L171: > movl $3, (%esp) > call printroots > call cons > movl %eax, w > movl $4, (%esp) > call printroots > > > movl w, %ebx <<<<<<<<<<<<<<< eager load of w is bug, given volatile w > call cons <<<<<<<<<<<<<<< side effect of cons changes w > movl %eax, car(,%ebx,4) > > > movl $5, (%esp) > call printroots > movl w, %eax > movl car(,%eax,4), %edx > movl s, %eax > movl car(,%eax,4), %eax > movl %eax, car(,%edx,4) > movl w, %eax > movl car(,%eax,4), %edx > movl s, %eax > movl cdr(,%eax,4), %eax > movl car(,%eax,4), %eax > movl %eax, cdr(,%edx,4) > movl w, %edx > movl s, %eax > movl cdr(,%eax,4), %eax > movl cdr(,%eax,4), %eax > movl %eax, cdr(,%edx,4) > movl w, %eax > movl %eax, s > movl c, %eax > movl cdr(,%eax,4), %eax > movl %eax, c > jmp .L144 > > > ---------------------------------------------------------------------------------------------------------------- > ---------------------------------------------------------------------------------------------------------------- > > ... > volatile int car[cnssz+1],cdr[cnssz+1],atom[tagsz+1],num[tagsz+1],markr[tagsz+1]; > volatile int s,e,c,d; > volatile int w; > volatile int t,f,nil,ff; > ... > case 13: > printroots(3); > w = cons(); > printroots(4); > tmptmp = cons(); > car[w]= tmptmp /*cons()*/; > printroots(5); > car[car[w]]=car[s]; > cdr[car[w]]=car[cdr[s]]; > cdr[w]=cdr[cdr[s]]; > s=w; > c = cdr[c]; > goto l1000; > ... > > generated code-- > .L171: > movl $3, (%esp) > call printroots > call cons > movl %eax, w > movl $4, (%esp) > call printroots > > > call cons > movl %eax, -24(%ebp) > movl w, %edx <<<<<<<<<<< reference to w moved by adding worthless code > movl -24(%ebp), %eax > movl %eax, car(,%edx,4) > > > movl $5, (%esp) > call printroots > movl w, %eax > movl car(,%eax,4), %edx > movl s, %eax > movl car(,%eax,4), %eax > movl %eax, car(,%edx,4) > movl w, %eax > movl car(,%eax,4), %edx > movl s, %eax > movl cdr(,%eax,4), %eax > movl car(,%eax,4), %eax > movl %eax, cdr(,%edx,4) > movl w, %edx > movl s, %eax > movl cdr(,%eax,4), %eax > movl cdr(,%eax,4), %eax > movl %eax, cdr(,%edx,4) > movl w, %eax > movl %eax, s > movl c, %eax > movl cdr(,%eax,4), %eax > movl %eax, c > jmp .L144