This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug inline-asm/58234] New: In-line asm version of __FD_ZERO in /usr/include/bits/select.h
- From: "baker at usgs dot gov" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 23 Aug 2013 22:23:43 +0000
- Subject: [Bug inline-asm/58234] New: In-line asm version of __FD_ZERO in /usr/include/bits/select.h
- Auto-submitted: auto-generated
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58234
Bug ID: 58234
Summary: In-line asm version of __FD_ZERO in
/usr/include/bits/select.h
Product: gcc
Version: 4.4.7
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: inline-asm
Assignee: unassigned at gcc dot gnu.org
Reporter: baker at usgs dot gov
I encountered a run-time error using the -check=uninit Intel icc compiler
option on Linux:
Run-Time Check Failure: The variable '__d1' is being used without being
initialized
I tracked the problem to the FD_ZERO macro, which is ultimately expanded using
the __FD_ZERO macro in /usr/include/bits/select.h. A very simple program will
trigger the run-time failure:
#include <sys/select.h>
int main( void ) {
fd_set rfds;
FD_ZERO( &rfds );
return 0;
}
Compiled with:
# icc -check=uninit intel.c
The fix is to disable the in-line asm code for __FD_ZERO; -no-gcc will suffice:
# icc -no-gcc -check=uninit intel.c
That is fine for this case. But the code I am working with needs other GNUC
header options that also get disabled when -no-gcc is used. If I add -no-gcc,
I get lots of compilation errors.
I realize this is not technically a GCC library/headers error. I think the
Intel icc compiler does not properly account for in-line asm side-effects in
its uninitialized variable tracking.
However, I decided to see if I could make the __FD_ZERO macro asm work. I was
able to rearrange the in-line asm for a workaround in this case. I think this
is an improvement, and also cures a subtle flaw in the original that (luckily)
makes absolutely no difference.
The original __FD_ZERO macro definition (in /usr/include/bits/select.h) is:
# define __FD_ZERO(fdsp) \
do { \
int __d0, __d1; \
__asm__ __volatile__ ("cld; rep; " __FD_ZERO_STOS \
: "=c" (__d0), "=D" (__d1) \
: "a" (0), "0" (sizeof (fd_set) \
/ sizeof (__fd_mask)), \
"1" (&__FDS_BITS (fdsp)[0]) \
: "memory"); \
} while (0)
I cannot tell exactly where in the expansion the Intel run-time error occurs --
gdb shows ?? for the backtrace beyond the Intel __intel_rtc_uninit_use()
service routine (compiled with -g):
(gdb) bt
#0 0x00130430 in __kernel_vsyscall ()
#1 0x001a3b11 in raise () from /lib/libc.so.6
#2 0x001a53ea in abort () from /lib/libc.so.6
#3 0x080489e1 in __intel_rtc_uninit_use ()
#4 0x00000001 in ?? ()
#5 0x00000000 in ?? ()
The assembly language generated by gcc -O0 (-m32 or -m64) always includes a
store into __d0 and __d1 after the execution of the stosl/stosq instruction.
Maybe it is that store which is tripping up the Intel code.
I rewrote the asm to remove __d0 and __d1, since they go out-of-scope anyway
after the asm executes:
# define __FD_ZERO(fdsp) \
do { \
__asm__ __volatile__ ("cld; rep; " __FD_ZERO_STOS \
: \
: "a" (0), \
"c" (sizeof (fd_set) / sizeof (__fd_mask)), \
"D" (&__FDS_BITS (fdsp)[0]) \
: "memory"); \
} while (0)
This generated slightly different code, which I believe is correct.
Here is the original assembly output for gcc -m32 and gcc -m64:
Original __FD_ZERO, gcc -m32
.file "junk.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
pushl %edi
subl $144, %esp
movl $0, %eax
movl $32, %ecx
leal -140(%ebp), %edx
movl %edx, %edi
#APP
# 45 "junk.c" 1
cld; rep; stosl
# 0 "" 2
#NO_APP
movl %edi, %edx
movl %ecx, -12(%ebp)
movl %edx, -8(%ebp)
movl $0, %eax
addl $144, %esp
popl %edi
popl %ebp
ret
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
.section .note.GNU-stack,"",@progbits
Original __FD_ZERO, gcc -m64
.file "junk.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $32, %rsp
movl $0, %eax
movl $16, %edx
leaq -160(%rbp), %rbx
.cfi_offset 3, -24
movq %rdx, %rcx
movq %rbx, %rdi
#APP
# 45 "junk.c" 1
cld; rep; stosq
# 0 "" 2
#NO_APP
movl %edi, %eax
movl %ecx, %edx
movl %edx, -24(%rbp)
movl %eax, -20(%rbp)
movl $0, %eax
addq $32, %rsp
popq %rbx
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
.section .note.GNU-stack,"",@progbits
(The subtle flaw I see is due to the use of int __d1 for an address on an
x86_64 machine. The completely useless and benign store into __d1 is always a
movl, even on an x86_64 machine. That is not technically correct. __d1 should
really be declared void * __d1.)
Here is the assembly output for gcc -m32 and gcc -m64 using the replacement
__FD_ZERO asm:
Replacement __FD_ZERO, gcc -m32
.file "junk.c"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %ebx
addl $-128, %esp
movl $0, %eax
movl $32, %edx
leal -136(%ebp), %ebx
movl %edx, %ecx
movl %ebx, %edi
#APP
# 45 "junk.c" 1
cld; rep; stosl
# 0 "" 2
#NO_APP
movl $0, %eax
subl $-128, %esp
popl %ebx
popl %edi
popl %ebp
ret
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
.section .note.GNU-stack,"",@progbits
Replacement __FD_ZERO, gcc -m64
.file "junk.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $16, %rsp
movl $0, %eax
movl $16, %edx
leaq -144(%rbp), %rbx
.cfi_offset 3, -24
movq %rdx, %rcx
movq %rbx, %rdi
#APP
# 45 "junk.c" 1
cld; rep; stosq
# 0 "" 2
#NO_APP
movl $0, %eax
addq $16, %rsp
popq %rbx
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
.section .note.GNU-stack,"",@progbits
The code is a little tighter: there is no allocation for __d0 and __d1 on the
stack, and the stores to __d0 and __d1 are of course also gone, since they no
longer exist.
What I do not know is how to tell the compiler that the instruction clobbers
%ecx and %edi as side-effects. I do not even know if that is necessary. I
tried adding them to the clobber list, but then the asm would not compile
(can't find a register in class âCREGâ while reloading âasmâ).
Someone more knowledgeable than I will have to say whether there are any loose
ends that need to be cleaned up.
I apologize if this is the wrong list to post this, and for being so
long-winded. I tried to be accurate and complete. Please steer me elsewhere,
if this post is inappropriate.
Thank you,
Larry Baker
US Geological Survey