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]

Possibel gcc Bug when compiling f2c generated C-Code


Hi gcc-team.

First our system specification:

gcc-3.4.1
glibc-2.3.4.20040808-r0
System uname: 2.6.7-gentoo-r11 x86_64 4
Binutils: sys-devel/binutils-2.15.90.0.1.1-r3
Headers:  sys-kernel/linux26-headers-2.6.7-r4
Libtools: sys-devel/libtool-1.5.2-r5
ACCEPT_KEYWORDS="amd64 ~amd64"
AUTOCLEAN="yes"
CFLAGS="-march=k8 -O2 -pipe -ftracer"
# Above CFLAGS trigger the bug. gcc has also been compiled
# with above flags.

# CFLAGS used for debugging are:
CFLAGS="-O2 -ggdb"


Please have a look at [1] first to get an impression of the bug to be
reported. It can be summarized like this. When the f2c programm is used
to translate the Fortran sources of the programm R-1.9.{0,1} to C
sources and then compiled using gcc -O2, R segfaults with following
programm:

x<-rnorm(1000);
y<-rnorm(1000);
lm(y~x);

Above programm works, if it is compiled using the GNU Fortran Compiler.

What doesn't work is this snippet of code ( see [2] for the full file ):

doublereal dnrm2_(integer *n, doublereal *x, integer *incx)
{
~    /* System generated locals */
~    integer i__1, i__2;
~    doublereal ret_val, d__1;

~    /* Builtin functions */
~    double sqrt(doublereal);

~    /* Local variables */
~    static integer ix;
~    static doublereal ssq, norm, scale, absxi;
[... Comments]
~    --x;

~    /* Function Body */
~    if (*n < 1 || *incx < 1) { // <-- This is blas.c:1570
~        norm = 0.;
~    } else if (*n == 1) {
~        norm = abs(x[1]);
~    } else {
~        scale = 0.;
~        ssq = 1.;
/*        The following loop is equivalent to this call to the LAPACK */
/*        auxiliary routine: */
/*        CALL DLASSQ( N, X, INCX, SCALE, SSQ ) */

~        i__1 = (*n - 1) * *incx + 1;
~        i__2 = *incx;
~        for (ix = 1; i__2 < 0 ? ix >= i__1 : ix <= i__1; ix += i__2) {
~            if (x[ix] != 0.) { // <-- This is blas.c:1584
~                absxi = (d__1 = x[ix], abs(d__1));
~                if (scale < absxi) {
[...]

When the function dnrm2_ is called like this:

~  dnrm2_(&i, &r, &c__1)

with c__1 being defined as:

static long int c__1 = 1;

we get the following segfault when running the already mentioned R
programm:

Program received signal SIGSEGV, Segmentation fault.
dnrm2_ (n=0x40000000000003e8, x=0x216c740, incx=0x1) at blas.c:1584
1584    blas.c: No such file or directory.
~        in blas.c
(gdb) bt
#0  dnrm2_ (n=0x40000000000003e8, x=0x216c740, incx=0x1) at blas.c:1584
#1  0x000000000051ee0d in dqrdc2_ (x=0x216a800, ldx=0x216c740,
n=0x206d0e0, p=0x206d0b0, tol=0x205c950, k=0x206d050,
~    qraux=0x1f84328, jpvt=0x205c910, work=0x1e6a648) at dqrdc2.c:133
[...]

You see, the pointer incx has the value of 0x1. But this is not the
value that the function got called with at the beginning.
incx got changed by following line from blas.s [3], generated by "gcc
- -O2 -ggdb -S blas.c" (for blas.c see [2], for the preprocessed file
see
[4]):

~        .type   dnrm2_, @function
dnrm2_:
.LFB10:
~        .loc 1 1533 0
~        subq    $8, %rsp
.LCFI28:
~        .loc 1 1570 0
~        movq    (%rdi), %rax
~        .loc 1 1567 0
~        subq    $8, %rsi
~        .loc 1 1570 0
~        testq   %rax, %rax
~        jle     .L748
~        movq    (%rdx), %rdx <-- this is the bogus line.
~        testq   %rdx, %rdx
~        jle     .L748
~        .loc 1 1572 0
~        cmpq    $1, %rax
~        je      .L771
~        .loc 1 1581 0
~        decq    %rax

The marked line is bogus, cause %rdx holds the pointer incx. This line
is the reason, why incx gets set to 0x1. It's the very value that the
static long int holds that incx points to.

However, when you ommit "-O2", the particular file looks like this:

~        .type   dnrm2_, @function
dnrm2_:
.LFB10:
~        pushq   %rbp
.LCFI21:
~        movq    %rsp, %rbp
.LCFI22:
~        subq    $80, %rsp
.LCFI23:
~        movq    %rdi, -8(%rbp)
~        movq    %rsi, -16(%rbp)
~        movq    %rdx, -24(%rbp)
~        leaq    -16(%rbp), %rax
~        subq    $8, (%rax)
~        movq    -8(%rbp), %rax
~        cmpq    $0, (%rax)
~        jle     .L444
~        movq    -24(%rbp), %rax
~        cmpq    $0, (%rax)
~        jle     .L444
~        jmp     .L443

And everything is fine. However, we found another way to get around this
bug.
When we commented the following line

#define abs(x) ((x) >= 0 ? (x) : -(x))

from /usr/include/f2c.h, this particular bug vanished. (But another one
stepped in: incx still
changes, but now it changes to 0x0 at a later line in the code.)

We haven't fully discovered what produces the second bug. But we think
that this first bug is very serious and should be
reported as quickly as possible.

For further questions, please mail us:

Benjamin Schindler <config@gmx.ch>
Danny van Dyk <kugelfang@gentoo.org>

or join #gentoo-amd64 on irc.freenode.net.

Benjamin & Danny

[1] http://bugs.gentoo.org/show_bug.cgi?id=61042
[2] http://dev.gentoo.org/~kugelfang/gcc-bug/blas.c
[3] http://dev.gentoo.org/~kugelfang/gcc-bug/blas.s
[4] http://dev.gentoo.org/~kugelfang/gcc-bug/blas.i
[5] http://dev.gentoo.org/~kugelfang/gcc-bug/blas.c-gcc-output.txt


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