Bug 769548

Summary: gcc -m32 on x86_64 generates usage of non-existing register
Product: Red Hat Enterprise Linux 6 Reporter: Stanislav Kozina <skozina>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: qe-baseos-tools-bugs
Severity: high Docs Contact:
Priority: high    
Version: 6.2CC: mhomolov
Target Milestone: rc   
Target Release: 6.3   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2011-12-21 10:14:26 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Attachments:
Description Flags
The reproducer source code none

Description Stanislav Kozina 2011-12-21 10:01:05 UTC
Description of problem:

Compilation of attached source code leads to operation on non-existing register.
Therefore the assembler cannot produce the binary.

Version-Release number of selected component (if applicable):

$ gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC)

How reproducible:

Always

Steps to Reproduce:
1. Compile the attached source code using $ gcc -S -m32 -O test.c
2. Assemble the assembled code using $ gcc -c -m32 test.s
3.
  
Actual results:

$ gcc -c -m32 test.s
test.c: Assembler messages:
test.c:3: Error: bad register name `%sil'

Expected results:

Assembler succeeds, the assembler code should not contain register '%sil'.

Additional info:

The source code contains inline assembler:
__asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
which is compiled into
	movb %sil,%fs:(%ecx,%edx)
(note the %sil register, which does not exist on i386).

It's the compiler which fills the actual registers into this instruction.
In short, we set 32-bit register, and then we need to read lowest 8 bits of it.
If the compiler would use one of %eax, %ebx, %ecx or %edx registers, everything would be fine.
But it uses %esi, which does not have its 8-bit variant.

The source code first does few loops and function calls - these are compiled into usage of all %ec* registers, so the compiler use %esi for inline assembler. Without these function calls it would use %eax.

Note that the %sil register actually exist on x86_64, because all legacy registers very extended to cover also 8-bit variants.

Comment 1 Stanislav Kozina 2011-12-21 10:02:16 UTC
Created attachment 549003 [details]
The reproducer source code

Comment 2 Jakub Jelinek 2011-12-21 10:14:26 UTC
The inline asm is just invalid.  If you have on i?86 an 8 bit value you want to put into a register, you must use "q" constraint for it instead of "r", only that ensures it will be allocated in %al/%bl/%cl/%dl and no other registers.