[Bug c/17432] New: Possible gcc bug when compiling f2c generated C-code

kugelfang at gentoo dot org gcc-bugzilla@gcc.gnu.org
Sun Sep 12 08:43:00 GMT 2004


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 generated C -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 line in f2c.h produces the second bug. But we
think that this first bug is very serious and should be reported as quickly as
possible.

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

Annotation:

This BUG Report had already been sent to gcc-bugs@gcc.gnu.org. James Wilson was
so kind to redirect us here. Further he suggested to compile gcc and the code
that actually produces this bug w/o the -ftracer flag. There was no visible effect.

-- 
           Summary: Possible gcc bug when compiling f2c generated C-code
           Product: gcc
           Version: 3.4.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: kugelfang at gentoo dot org
                CC: gcc-bugs at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17432



More information about the Gcc-bugs mailing list