From: burgers AT ecn DOT nl (Teun Burgers) Subject: BUG: __stdcall calling convention generates wrong assembly 29 Mar 1998 18:55:09 -0800 Message-ID: <199803260800.AA18074.cygnus.gnu-win32@joost.ecn.nl> Content-Transfer-Encoding: 7BIT To: gnu-win32 AT cygnus DOT com 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 (burgers AT ecn DOT nl) Ton van Overbeek (tvoverbe AT wk DOT estec DOT esa DOT nl) ---- bug.c starts here ------- #include #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 "gnu-win32-request AT cygnus DOT com" with one line of text: "help".