December 31, 2012
http://gdcproject.org/bugzilla/show_bug.cgi?id=33

             Bug #: 33
           Summary: Illegal instruction reordering with O2
    Classification: Unclassified
           Product: GDC
           Version: development
          Platform: x86_64
        OS/Version: Linux
            Status: NEW
          Severity: major
          Priority: Normal
         Component: gdc
        AssignedTo: ibuclaw@gdcproject.org
        ReportedBy: johannespfau@gmail.com


I'm not totally sure if my conclusion is right, but this is a strange bug:

Testcase: (fails with -O2, ok without)
----------
import std.typecons;

void main()
{
    class A { int x = 1; }
    auto a1 = scoped!A();
    assert(a1.x == 1);
}
----------

Testcase2: (OK with -O2)
----------
import std.typecons, std.stdio;

void main()
{
    class A { int x = 1; }
    auto a1 = scoped!A();
    writeln();
    assert(a1.x == 1);
}
----------

Disassembler for failing test:
----------
   0x0000000000cd9960 <+0>:    push   %rbp
   0x0000000000cd9961 <+1>:    push   %rbx
   0x0000000000cd9962 <+2>:    sub    $0x98,%rsp
   0x0000000000cd9969 <+9>:    mov    %rsp,%rdi
   0x0000000000cd996c <+12>:    lea    0x30(%rsp),%rbx
   0x0000000000cd9971 <+17>:    callq  0xce89b0
<_D3std8typecons45__T6scopedTC3std8typecons12__unittest41FZv1AZ6scopedFZS3std8typecons45__T6scopedTC3std8typecons12__unittest41FZv1AZ6scoped45__T6ScopedTC3std8typecons12__unittest41FZv1AZ6Scoped>
   0x0000000000cd9976 <+22>:    mov    (%rsp),%rax
=> 0x0000000000cd997a <+26>:    cmpl   $0x1,0x10(%rbx)
----------

Disassembler for working test:
----------
   0x0000000000cd9970 <+0>:    push   %r12
   0x0000000000cd9972 <+2>:    push   %rbp
   0x0000000000cd9973 <+3>:    push   %rbx
   0x0000000000cd9974 <+4>:    sub    $0x90,%rsp
   0x0000000000cd997b <+11>:    mov    %rsp,%rdi
   0x0000000000cd997e <+14>:    lea    0x30(%rsp),%rbp
   0x0000000000cd9983 <+19>:    callq  0xce89d0
<_D3std8typecons45__T6scopedTC3std8typecons12__unittest41FZv1AZ6scopedFZS3std8typecons45__T6scopedTC3std8typecons12__unittest41FZv1AZ6scoped45__T6ScopedTC3std8typecons12__unittest41FZv1AZ6Scoped>
   0x0000000000cd9988 <+24>:    mov    (%rsp),%rax
   0x0000000000cd998c <+28>:    mov    %rax,0x30(%rsp)
   0x0000000000cd9991 <+33>:    mov    0x8(%rsp),%rax
   0x0000000000cd9996 <+38>:    mov    %rax,0x38(%rsp)
   0x0000000000cd999b <+43>:    mov    0x10(%rsp),%rax
   0x0000000000cd99a0 <+48>:    mov    %rax,0x40(%rsp)
   0x0000000000cd99a5 <+53>:    mov    0x18(%rsp),%rax
   0x0000000000cd99aa <+58>:    mov    %rax,0x48(%rsp)
   0x0000000000cd99af <+63>:    mov    0x20(%rsp),%rax
   0x0000000000cd99b4 <+68>:    mov    %rax,0x50(%rsp)
   0x0000000000cd99b9 <+73>:    callq  0xa15ba0
<_D3std5stdio12__T7writelnZ7writelnFZv>
   0x0000000000cd99be <+78>:    lea    0x30(%rsp),%rbp
=> 0x0000000000cd99c3 <+83>:    cmpl   $0x1,0x10(%rbp)
----------

The <...Scoped> functions are identical.

Now my x86 asm understanding is pretty bad, but what looks odd to me is that in the working example "lea    0x30(%rsp),%rbp" is called after calling the <...Scoped> helper function but in the not working example "lea 0x30(%rsp),%rbx" is called before calling the function. And rbx is supposed to contain the pointer to the payload, which can only be obtained by calling <...Scoped>. It seems the compiler moved the lea instruction for some reason.

Tested with:
GDC rev 102ab270
gcc-4.8-20121021

-- 
Configure issuemail: http://gdcproject.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are watching all issue changes.