The bug occurs when I compile the following code: =========================================================== __attribute__((stdcall)) int (*P)(int A, int B, int C) = 0;
__attribute__((stdcall)) int X(int A, int B, int C) { if(A) return P(A, B, C); return P(42, B, C); } =========================================================== (This is the full file after trimming everything unrelated to the problem. You can paste this in a file.) Note that P is a callback. It got filled in somewhere else, but this is all the code needed to see the problem manifest itself. The bug only shows up if: * P is a function pointer. * Both P and X are stdcall. * P and X have at least three arguments. * Tail call optimisation is done. * Double call optimisation is done. For the last two reasons I tagged the bug rtl-optimisation, since I think it's highly likely that it's an optimisation problem. I compile this code using the following command: $ gcc bug.cpp -S bug.s -Os -fomit-frame-pointer -masm=intel The last two parameters are not necessary to make the bug manifest itself, but this way it hides in a lot less generated assembler output. No errors or warnings are generated, but the result is: ====================================================================== .file "bug.cpp" .intel_syntax .globl _P .bss .align 4 _P: .space 4 .text .align 2 .globl __z1x...@12 .def __z1x...@12; .scl 2; .type 32; .endef __z1x...@12: push ebx mov edx, DWORD PTR [esp+8] mov ecx, DWORD PTR [esp+12] mov eax, DWORD PTR [esp+16] test edx, edx jne L3 mov DWORD PTR [esp+16], eax mov DWORD PTR [esp+12], ecx mov DWORD PTR [esp+8], 42 L3: pop ebx jmp ebx ====================================================================== (Note that numbers are decimal.) When not all the conditions for the bug to appear are fulfilled, whatever register the final jmp takes gets set to the right value using a mov instruction. But in this case, the mov instruction doesn't get emitted and the register is wrong. So instead of calling the callback function, the code jumps to the Elysian Fields. Note: I don't know why it push-pops ebx, since it doesn't get touched. Similarly, I don't know what some of the mov instructions are hoping to accomplish. Otherwise, the code is correct, and if the bug-triggering conditions mentioned aren't present, the callback gets called and correctly returns the right result. Version: gcc.exe (GCC) 3.4.5 (mingw-vista special r3) Platform: x86 Win32 -- Summary: -Os generates wrong code when stdcall function with 3+ arguments does double tail call via function pointer. Product: gcc Version: 3.4.5 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: congruwer at yahoo dot co dot uk GCC build triplet: Idem. I apologize. GCC host triplet: Don't know what this is or how to obtain it and a web search did GCC target triplet: Likewise. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42433