This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug rtl-optimization/42433] New: -Os generates wrong code when stdcall function with 3+ arguments does double tail call via function pointer.
- From: "congruwer at yahoo dot co dot uk" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 19 Dec 2009 09:11:20 -0000
- Subject: [Bug rtl-optimization/42433] New: -Os generates wrong code when stdcall function with 3+ arguments does double tail call via function pointer.
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
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 __Z1Xiii@12
.def __Z1Xiii@12; .scl 2; .type 32; .endef
__Z1Xiii@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