This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug inline-asm/58234] New: In-line asm version of __FD_ZERO in /usr/include/bits/select.h


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]