This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug rtl-optimization/42433] New: -Os generates wrong code when stdcall function with 3+ arguments does double tail call via function pointer.


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]