Subject: BUG: __stdcall calling convention generates wrong assembly
From: [email-masked] (Teun Burgers)

29 Mar 1998 18:55:09 -0800
Message-ID: <[email-masked]>
Content-Transfer-Encoding: 7BIT
To: [email-masked]

DESCRIPTION
    gcc versions 2.8.0 and 2.8.1 on both the mingw32 platform and
    the Cygnus port generate wrong assembly code for functions
    returning a double or a float when these functions have
    the __attribute__((stdcall)). The caller gets NaN from
    these functions.
    This problem is mainly relevant to DLL building for other
    win32 applications. Functions in the WINAPI often use the
    __attribute__((stdcall)) convention.

    This is message is a repost of the following message:

    http://www.cygnus.com/ml/gnu-win32/1998-Mar/0964.html

    because bug.c in that message was base64 encoded.

REPRODUCTION OF THE PROBLEM
    The problem can be reproduced in a 10-line c-program that is
    included in this message. When compiled with the following command
    line the problem is demonstrated:

    gcc -DPASCAL -o bug.exe bug.c

    When compile without -DPASCAL it works OK.

ANALYSIS
    When one compares the assembly from the standard c-calling sequence
    and the code with the __attribute__((stdcall)), the latter has an
    extra fstp instruction, that scrambles the stack.

WORKAROUND
    A workaround is available. Compile the C-code with the -S
    option. Remove the line with the fstp %st(0) instruction
    from the assembly and compile the edited assembly.

PARTIAL WORKAROUND
    A partial workaround (due to Colin Peters) is to compile with the
    -mno-fp-ret-in-387 option. In this case calling the function in gcc
    will give the correct result. This does not work however in a DLL
    that is used by other packages, for instance MS-Excel or the Java
    Development Kit from Sun.

Teun Burgers             ([email-masked])
Ton van Overbeek    ([email-masked])

---- bug.c starts here -------

#include <stdio.h>

#ifdef PASCAL
#define CALLCONV __attribute__((stdcall))
#else
#define CALLCONV
#endif PASCAL

double CALLCONV hellodd (double x)
{
 printf("hellodd: x before exit %g\n",x);
 return x;
}

int main () {
 double x = 10, z;
 z = hellodd(x);
 printf("z after call of hellodd: %g\n",z);
 return 0;
}
-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".